Java/함수형 인터페이스

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

DevStory 2022. 8. 25.

Predicate 인터페이스

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

@FunctionalInterface
public interface Predicate<T> {
  boolean test(T t);

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

  default Predicate<T> negate() {
    return (t) -> !test(t);
  }

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

  static <T> Predicate<T> isEqual(Object targetRef) {
    return (null == targetRef)
            ? Objects::isNull
            : object -> targetRef.equals(object);
  }
}

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

 

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

 

[추상 메서드 목록]

- test() 메서드

 

[디폴트 메서드 목록]

- and() 메서드

- negate() 메서드

- or() 메서드

 

[정적 메서드 목록]

- isEqual() 메서드

 

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


Predicate 인터페이스의 test 메서드

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

boolean test(T t);

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

 

다음 예제는 String 타입인 매개변수의 값의 첫 번째 문자열이 "A"인 경우 true를 반환하고 그렇지 않으면 false를 반환하는 람다 표현식을 Predicate 타입의 객체에 할당 후 test() 메서드에 문자열을 전달합니다.

public static void main(String args[]) {
  Predicate <String> predicate =
          (strValue) -> strValue.startsWith("A");

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

  System.out.println("predicate.test(\"BCD\"): " +
          predicate.test("BCD"));

  System.out.println("predicate.test(\"한글\"): " +
          predicate.test("한글"));
}

[실행 결과]

predicate.test("ABC"): true
predicate.test("BCD"): false
predicate.test("한글"): false

Predicate 인터페이스의 and 메서드

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

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

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

 

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

 

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

 

Predicate 타입의 객체인 predicate는 String 타입의 매개변수를 가지며, 첫 번째 문자열이 "A"인 경우 true를 반환하고 그렇지 않으면 false를 반환하는 람다 표현식이 할당되었습니다.

 

and() 메서드에는 String 타입의 매개변수를 가지며, 마지막 문자열이 "Z"인 경우 true를 반환하고 그렇지 않으면 false를 반환하는 람다 표현식을 전달합니다.

public static void main(String args[]) {
  Predicate <String> predicate =
          (strValue) -> strValue.startsWith("A");

  // 문자열 "ABC"의 첫 문자는 "A"이므로 true
  // 문자열 "ABC"의 마지막 문자는 "C"이므로 false
  // true && false의 결과는 false
  System.out.println("\"ABC\"는 \"A\"로 시작하고 \"Z\"로 끝나는가? " +
          predicate.and((strValue) -> strValue.endsWith("Z")).test("ABC"));

  // 문자열 "ABZ"의 첫 문자는 "A"이므로 true
  // 문자열 "ABZ"의 마지막 문자는 "Z"이므로 true
  // true && true의 결과는 true
  System.out.println("\"ABZ\"는 \"A\"로 시작하고 \"Z\"로 끝나는가? " +
          predicate.and((strValue) -> strValue.endsWith("Z")).test("ABZ"));

  // 문자열 "BCZ"의 첫 문자는 "B"이므로 false
  // 문자열 "BCZ"의 마지막 문자는 "Z"이므로 true
  // false && true의 결과는 false
  System.out.println("\"BCZ\"는 \"A\"로 시작하고 \"Z\"로 끝나는가? " +
          predicate.and((strValue) -> strValue.endsWith("Z")).test("BCZ"));
}

[실행 결과]

"ABC"는 "A"로 시작하고 "Z"로 끝나는가? false
"ABZ"는 "A"로 시작하고 "Z"로 끝나는가? true
"BCZ"는 "A"로 시작하고 "Z"로 끝나는가? false

Predicate 인터페이스의 negate 메서드

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

default Predicate<T> negate() {
  return (t) -> !test(t);
}

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

 

Integer 타입인 매개변수의 값이 100보다 크면 true를 반환하고 그렇지 않으면 false를 반환하는 람다 표현식을 Predicate 타입의 객체에 할당 후 negate() 메서드 뒤에 test() 메서드를 호출합니다.

public static void main(String args[]) {
  Predicate <Integer> predicate =
          (num) -> num > 100 ? true : false;

  // 10은 100보다 작으므로 false
  // negate() 메서드에 의해 true를 반환
  System.out.println("predicate.negate().test(10): " +
          predicate.negate().test(10));

  // 1000은 100보다 크므로 true
  // negate() 메서드에 의해 false를 반환
  System.out.println("predicate.negate().test(1000): " +
          predicate.negate().test(1000));
}

[실행 결과]

predicate.negate().test(10): true
predicate.negate().test(1000): false

Predicate 인터페이스의 or 메서드

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

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

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

 

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

public static void main(String args[]) {
  Predicate <String> predicate =
          (strValue) -> strValue.startsWith("A");

  // 문자열 "ABC"의 첫 문자는 "A"이므로 true
  // 문자열 "ABC"의 마지막 문자는 "C"이므로 false
  // true || false의 결과는 true
  System.out.println("\"ABC\"는 \"A\"로 시작하거나 또는 \"Z\"로 끝나는가? " +
          predicate.or((strValue) -> strValue.endsWith("Z")).test("ABC"));

  // 문자열 "ABZ"의 첫 문자는 "A"이므로 true
  // 문자열 "ABZ"의 마지막 문자는 "Z"이므로 true
  // true || true의 결과는 true
  System.out.println("\"ABZ\"는 \"A\"로 시작하거나 또는 \"Z\"로 끝나는가? " +
          predicate.or((strValue) -> strValue.endsWith("Z")).test("ABZ"));

  // 문자열 "BCZ"의 첫 문자는 "B"이므로 false
  // 문자열 "BCZ"의 마지막 문자는 "Z"이므로 true
  // false || true의 결과는 true
  System.out.println("\"BCZ\"는 \"A\"로 시작하거나 또는 \"Z\"로 끝나는가? " +
          predicate.or((strValue) -> strValue.endsWith("Z")).test("BCZ"));
}

[실행 결과]

"ABC"는 "A"로 시작하거나 또는 "Z"로 끝나는가? true
"ABZ"는 "A"로 시작하거나 또는 "Z"로 끝나는가? true
"BCZ"는 "A"로 시작하거나 또는 "Z"로 끝나는가? true
반응형

댓글