Java/함수형 인터페이스

[Java]BiPredicate 인터페이스 사용 방법

DevStory 2022. 8. 24.

BiPredicate 인터페이스

BiPredicate Interface는 Java에서 함수형 프로그래밍을 구현하기 위해 Java 버전 1.8부터 도입된 함수형 인터페이스로 제네릭 타입인 두 개의 매개변수를 전달받아 특정 작업을 수행 후 Boolean 타입의 값을 반환하는 작업을 수행할 때, 사용됩니다.

@FunctionalInterface
public interface BiPredicate<T, U> {
  boolean test(T t, U u);

  default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> other) {
    Objects.requireNonNull(other);
    return (T t, U u) -> test(t, u) && other.test(t, u);
  }

  default BiPredicate<T, U> negate() {
    return (T t, U u) -> !test(t, u);
  }

  default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> other) {
    Objects.requireNonNull(other);
    return (T t, U u) -> test(t, u) || other.test(t, u);
  }
}

BiPredicate 인터페이스는 두 개의 제네릭 타입을 사용합니다.

T: 첫 번째 매개변수의 타입입니다.

U: 두 번째 매개변수의 타입입니다.

 

BiPredicate 인터페이스 내부에는 한 개의 추상 메서드와 세 개의 디폴트 메서드가 존재합니다.

 

[추상 메서드 목록]

- test() 메서드

 

[디폴트 메서드 목록]

- and() 메서드

- negate() 메서드

- or() 메서드

 

람다 표현식을 사용하면 추상 메서드인 test() 메서드를 구현하기 위해 클래스를 정의할 필요가 없으며, BiPredicate 타입의 객체에 할당된 람다 표현식은 test() 메서드를 구현하기 위해 사용됩니다.


BiPredicate 인터페이스의 test 메서드

test() 메서드는 제네릭 타입인 두 개의 매개변수를 전달받아 특정 작업을 수행 후 Boolean 값을 반환합니다.

boolean test(T t, U u);

test() 메서드를 구현하기 위해 두 개의 매개변수를 가지며, Boolean 타입의 값을 반환하는 람다 표현식을 BiPredicate 타입의 객체에 할당합니다. 람다 표현식은 test() 메서드를 구현합니다.

 

다음 예제는 String 타입인 두 매개변수의 값을 equals() 메서드로 비교하는 람다 표현식을 BiPredicate 타입의 객체에 할당 후 test() 메서드에 두 개의 문자열을 전달합니다.

public static void main(String args[]) {
  BiPredicate <String, String> biPredicate =
          (str1, str2) -> str1.equals(str2);

  System.out.println("biPredicate.test(\"ABC\", \"ABC\"): " +
          biPredicate.test("ABC", "ABC"));

  System.out.println("biPredicate.test(\"abc\", \"ABC\"): " +
          biPredicate.test("abc", "ABC"));
}

[실행 결과]

biPredicate.test("ABC", "ABC"): true
biPredicate.test("abc", "ABC"): false

BiPredicate 인터페이스의 and 메서드

BiPredicate 인터페이스의 디폴트 메서드인 and() 메서드는 BiPredicate 타입의 객체를 매개변수로 가집니다.

default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> other) {
  Objects.requireNonNull(other);
  return (T t, U u) -> test(t, u) && other.test(t, u);
}

test() 메서드 반환 결과와 and() 메서드의 매개변수로 전달된 BiPredicate 객체의 test() 메서드 반환 결과에 대해 and 연산을 수행합니다.

 

and() 메서드의 매개변수로 BiPredicate 객체 대신 두 개의 매개변수를 가지며, Boolean 타입의 값을 반환하는 람다 표현식을 전달할 수 있습니다.

 

다음 예제는 and() 메서드 사용 방법을 보여줍니다.

 

BiPredicate 타입의 객체인 biPredicate는 Integer 타입의 두 매개변수를 가지며 두 값의 합이 100보다 크면 true를 반환하고 그렇지 않으면 false를 반환하는 람다 표현식이 할당되었습니다.

 

biPredicate 객체 뒤에 and() 메서드를 호출하며, (첫 번째 매개변수 - 두 번째 매개변수)의 값이 0보다 크면 true를 반환하고 그렇지 않으면 false를 반환하는 람다 표현식을 전달합니다.

public static void main(String args[]) {
  BiPredicate <Integer, Integer> biPredicate =
          (num1, num2) -> (num1 + num2) > 100 ? true : false;

  // (50 + 30)이 100보다 작으므로 false
  // (50 - 30)이 0보다 크므로 true
  // false && true의 결과는 false
  System.out.println("50과 30을 전달: " +
          biPredicate.and((num1, num2) -> (num1 - num2) > 0 ? true : false)
                     .test(50, 30));

  // (30 + 80)이 100보다 크므로 true
  // (30 - 80)이 0보다 작으므로 false
  // true && false 결과는 false
  System.out.println("30과 80을 전달: " +
          biPredicate.and((num1, num2) -> (num1 - num2) > 0 ? true : false)
                     .test(30, 80));

  // (80 + 50)이 100보다 크므로 true
  // (80 - 50)이 0보다 크므로 true
  // true && true 결과는 true
  System.out.println("80과 50을 전달: " +
          biPredicate.and((num1, num2) -> (num1 - num2) > 0 ? true : false)
                     .test(80, 50));
}

[실행 결과]

50과 30을 전달: false
30과 50을 전달: false
80과 50을 전달: true

BiPredicate 인터페이스의 negate 메서드

BiPredicate 인터페이스의 디폴트 메서드인 negate() 메서드는 매개변수를 가지지 않으며, test() 메서드의 반환 결과를 부정합니다.

default BiPredicate<T, U> negate() {
  return (T t, U u) -> !test(t, u);
}

다음 예제는 negate() 메서드 사용 방법을 보여줍니다.

 

Integer 타입의 두 매개변수의 합이 100보다 크면 true를 반환하고 그렇지 않으면 false를 반환하는 람다 표현식을 BiPredicate 타입의 객체에 할당합니다.

 

negate() 메서드 뒤에 test() 메서드를 연결합니다.

public static void main(String args[]) {
  BiPredicate <Integer, Integer> biPredicate =
          (num1, num2) -> (num1 + num2) > 100 ? true : false;

  // (50 + 30)이 100보다 작으므로 false
  // negate() 메서드에 의해 true를 반환
  System.out.println("50과 30을 전달: " +
          biPredicate.negate().test(50, 30));

  // (30 + 80)이 100보다 크므로 true
  // negate() 메서드에 의해 false를 반환
  System.out.println("30과 80을 전달: " +
          biPredicate.negate().test(30, 80));

  // (80 + 50)이 100보다 크므로 true
  // negate() 메서드에 의해 false를 반환
  System.out.println("80과 50을 전달: " +
          biPredicate.negate().test(80, 50));
}

[실행 결과]

50과 30을 전달: false
30과 80을 전달: true
80과 50을 전달: true

nagate() 메서드는 메서드 체이닝 기법으로 여러 번 연결할 수 있습니다.

 

다음 예제는 negate() 메서드 뒤에 또 negate() 메서드를 호출합니다.

public static void main(String args[]) {
  BiPredicate <Integer, Integer> biPredicate =
          (num1, num2) -> (num1 + num2) > 100 ? true : false;

  // (50 + 30)이 100보다 작으므로 false
  // 첫 번째, negate() 메서드에 의해 true를 반환
  // 두 번째, negate() 메서드에 의해 false를 반환
  System.out.println("50과 30을 전달: " +
          biPredicate.negate().negate().test(50, 30));

  // (30 + 80)이 100보다 크므로 true
  // 첫 번째, negate() 메서드에 의해 false를 반환
  // 두 번째, negate() 메서드에 의해 true를 반환
  System.out.println("30과 80을 전달: " +
          biPredicate.negate().negate().test(30, 80));

  // (80 + 50)이 100보다 크므로 true
  // 첫 번째, negate() 메서드에 의해 false를 반환
  // 두 번째, negate() 메서드에 의해 true를 반환
  System.out.println("80과 50을 전달: " +
          biPredicate.negate().negate().test(80, 50));
}

[실행 결과]

50과 30을 전달: false
30과 80을 전달: true
80과 50을 전달: true

BiPredicate 인터페이스의 or 메서드

BiPredicate 인터페이스의 디폴트 메서드인 or() 메서드는 and() 메서드와 매개변수가 동일합니다. 따라서, BiPredicate 타입의 객체를 전달하거나 또는 두 개의 매개변수를 가지며, Boolean 타입의 값을 반환하는 람다식을 전달합니다.

default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> other) {
  Objects.requireNonNull(other);
  return (T t, U u) -> test(t, u) || other.test(t, u);
}

test() 메서드 반환 결과와 or() 메서드의 매개변수로 전달된 BiPredicate 객체의 test() 메서드 반환 결과에 대해 or 연산을 수행합니다.

 

다음 예제는 or() 메서드 사용 방법을 보여줍니다. and() 메서드에서 설명한 소스 코드와 큰 차이가 없으므로 설명은 생략합니다.

public static void main(String args[]) {
  BiPredicate <Integer, Integer> biPredicate =
          (num1, num2) -> (num1 + num2) > 100 ? true : false;

  // (10 + 30)이 100보다 작으므로 false
  // (10 - 30)이 0보다 작으므로 false
  // false || false의 결과는 false
  System.out.println("10과 30을 전달: " +
          biPredicate.or((num1, num2) -> (num1 - num2) > 0 ? true : false)
                     .test(10, 30));

  // (30 + 80)이 100보다 크므로 true
  // (30 - 80)이 0보다 작으므로 false
  // true || false 결과는 true
  System.out.println("30과 80을 전달: " +
          biPredicate.or((num1, num2) -> (num1 - num2) > 0 ? true : false)
                     .test(30, 80));

  // (80 + 50)이 100보다 크므로 true
  // (80 - 50)이 0보다 크므로 true
  // true || true 결과는 true
  System.out.println("80과 50을 전달: " +
          biPredicate.or((num1, num2) -> (num1 - num2) > 0 ? true : false)
                     .test(80, 50));
}

[실행 결과]

10과 30을 전달: false
30과 80을 전달: true
80과 50을 전달: true
반응형

댓글