자바의 술어


100

PredicateJava에서 사용하는 코드를 살펴 보겠습니다 . 나는 한 번도 사용하지 않았습니다 Predicate. 누군가 Predicate가 Java에 대한 자습서 또는 개념 설명 및 구현을 안내해 줄 수 있습니까 ?


4
당신은 구아바에 대해 말하고 Predicate있습니까? 비슷한 것? 완전히 다른 것?
polygenelubricants

2
Apache Commons도 있습니다Predicate
Dan Gravell

답변:


203

나는 당신이 com.google.common.base.Predicate<T>구아바에서 이야기하고 있다고 가정하고 있습니다 .

API에서 :

주어진 입력에 대한 true또는 false값을 결정합니다 . 예를 들어 a RegexPredicate는를 구현 Predicate<String>하고 주어진 정규식과 일치하는 모든 문자열에 대해 true를 반환 할 수 있습니다 .

이것은 본질적으로 boolean테스트를 위한 OOP 추상화입니다 .

예를 들어 다음과 같은 도우미 메서드가있을 수 있습니다.

static boolean isEven(int num) {
   return (num % 2) == 0; // simple
}

이제가 주어지면 다음 List<Integer>과 같이 짝수 만 처리 할 수 ​​있습니다.

    List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
    for (int number : numbers) {
        if (isEven(number)) {
            process(number);
        }
    }

를 사용 Predicate하면 if테스트가 유형으로 추상화됩니다. 이를 통해를 사용하는 Iterables많은 유틸리티 메서드가있는 과 같은 나머지 API와 상호 운용 할 수 있습니다 Predicate.

따라서 이제 다음과 같이 작성할 수 있습니다.

    Predicate<Integer> isEven = new Predicate<Integer>() {
        @Override public boolean apply(Integer number) {
            return (number % 2) == 0;
        }               
    };
    Iterable<Integer> evenNumbers = Iterables.filter(numbers, isEven);

    for (int number : evenNumbers) {
        process(number);
    }

이제 for-each 루프는 if테스트 없이 훨씬 더 간단합니다 . 우리는 정의하여 abtraction의 높은 수준에 도달했습니다 Iterable<Integer> evenNumbers에 의해, filter사용 a -ing Predicate.

API 링크


고차 함수

PredicateIterables.filter고차 함수라고하는 역할을 할 수 있습니다. 그 자체로 많은 이점을 제공합니다. List<Integer> numbers위 의 예를 보십시오 . 모든 숫자가 양수인지 테스트한다고 가정 해 보겠습니다. 다음과 같이 작성할 수 있습니다.

static boolean isAllPositive(Iterable<Integer> numbers) {
    for (Integer number : numbers) {
        if (number < 0) {
            return false;
        }
    }
    return true;
}

//...
if (isAllPositive(numbers)) {
    System.out.println("Yep!");
}

를 사용 Predicate하고 나머지 라이브러리와 상호 운용 하면 대신 다음과 같이 작성할 수 있습니다.

Predicate<Integer> isPositive = new Predicate<Integer>() {
    @Override public boolean apply(Integer number) {
        return number > 0;
    }       
};

//...
if (Iterables.all(numbers, isPositive)) {
    System.out.println("Yep!");
}

이제 "주어진 술어로 모든 요소 필터링", "모든 요소가 주어진 술어를 충족하는지 확인"등과 같은 루틴에 대한 더 높은 추상화에서 값을 볼 수 있기를 바랍니다.

불행히도 Java에는 1 급 메서드가 없습니다 . 및에 메서드 를 전달할 수 없습니다 . 물론 Java에서 객체 를 전달할 수 있습니다 . 따라서 유형이 정의되고 대신이 인터페이스를 구현하는 객체 를 전달 합니다 .Iterables.filterIterables.allPredicate

또한보십시오


4
나는 Guava의 술어를 언급하지 않았고, 나는 내 질문에 명확해야했지만, 당신의 설명은 내가 찾던 것, 즉 술어 논리가 자바에서 사용되는 방식을 이해하는 데 도움이되었습니다. 정교한 설명을 주셔서 감사합니다
스리 칸스

@polygenelubricants, Predicate<Integer>우리가 이미 F<Integer, Boolean>똑같은 것을 가지고 있는데 왜 발명 합니까?
Pacerier 2014-08-14

자바 8 방식으로도 할 수 있습니다 : List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); Predicate<Integer> isEven = integer -> (integer % 2) == 0; Iterable<Integer> evenNumbers = numbers.stream().filter(isEven).collect(Collectors.toList());

14

술어는 참 / 거짓 (즉, 부울) 값인 명제와 반대로 참 / 거짓 (즉, 부울) 값을 반환하는 함수입니다. Java에서는 독립형 함수를 가질 수 없으므로 술어를 나타내는 객체에 대한 인터페이스를 만들어 술어를 만든 다음 해당 인터페이스를 구현하는 클래스를 제공합니다. 술어에 대한 인터페이스의 예는 다음과 같습니다.

public interface Predicate<ARGTYPE>
{
    public boolean evaluate(ARGTYPE arg);
}

그리고 다음과 같은 구현이있을 수 있습니다.

public class Tautology<E> implements Predicate<E>
{
     public boolean evaluate(E arg){
         return true;
     }
}

더 나은 개념 이해를 위해 1 차 논리에 대해 읽어 볼 수 있습니다.

편집 Java 8부터 Java API에 정의 된
표준 Predicate 인터페이스 ( java.util.function.Predicate )가 있습니다. Java 8 이전에는 com.google.common.base.Predicate 인터페이스 를 재사용하는 것이 편리 할 수 있습니다. 구아바 .

또한 Java 8에서는 람다를 사용하여 술어를 작성하는 것이 훨씬 간단합니다. 예를 들어 Java 8 이상에서는 p -> true위와 같이 명명 된 Tautology 하위 클래스를 정의하는 대신 함수에 전달할 수 있습니다 .


0

여기 에서 Java 문서 예제 또는 Predicate 사용 예제를 볼 수 있습니다.

기본적으로 보유 할 수있는 특정 기준에 따라 결과 집합의 행을 필터링하고 기준을 충족하는 행에 대해 true를 반환하는 데 사용됩니다.

 // the age column to be between 7 and 10
    AgeFilter filter = new AgeFilter(7, 10, 3);

    // set the filter.
    resultset.beforeFirst();
    resultset.setFilter(filter);

나는 Resultset과 관련된 것이 아니라 commons 술어를 언급하고 있었다. 감사하지만
스리 칸스

0

Micheal에 추가 이 말한 :

Java에서 콜렉션을 필터링 할 때 다음과 같이 Predicate를 사용할 수 있습니다.

public static <T> Collection<T> filter(final Collection<T> target,
   final Predicate<T> predicate) {
  final Collection<T> result = new ArrayList<T>();
  for (final T element : target) {
   if (predicate.apply(element)) {
    result.add(element);
   }
  }
  return result;
}

가능한 술어는 다음과 같습니다.

final Predicate<DisplayFieldDto> filterCriteria = 
                    new Predicate<DisplayFieldDto>() {
   public boolean apply(final DisplayFieldDto displayFieldDto) {
    return displayFieldDto.isDisplay();
   }
  };

용법:

 final List<DisplayFieldDto> filteredList=
 (List<DisplayFieldDto>)filter(displayFieldsList, filterCriteria);

1
그것은 기본적으로 목적을 무너 뜨리지 않습니까? 기능적 접근 방식을 선택하는 주된 이유는 수동으로 반복하지 않고 for를 제거하는 것입니다. 추상화 수준은 더 높고 강력 해지지 만 수동으로 for를 수행하면 해당 목적이 무효화되고 낮은 수준의 추상화로 돌아갑니다.
Eugen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.