Javaの述語


100

PredicateJava で使用するコードを調べています。使ったことがないPredicate。誰かが私をチュートリアルまたはPredicateJavaでの実装の概念的な説明に案内できますか?


4
グアバについて話していますPredicateか?似たような?他に完全に何か?
polygenelubricants

2
また、Apache CommonsPredicate
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テストは型として抽象化されます。これにより、などのAPIの他の部分と相互運用できるようになりIterablesます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);
    }

ifテストがないとfor-eachループがはるかに簡単になることに注意してください。私たちは、定義することによってabtractionのより高いレベルに達したIterable<Integer> evenNumbersことで、filter使用して-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には一流のメソッドがありません。メソッドIterables.filterとに渡すことはできませんIterables.all。もちろん、Javaでオブジェクトを渡すことができます。したがって、Predicate型が定義され、代わりにこのインターフェイスを実装するオブジェクトを渡します

こちらもご覧ください


4
私はグアバの述語について言及していませんでしたが、質問では明確でしたが、あなたの説明は私が何を探しているのか、述語ロジックがJavaで使用されている方法を理解するのに役立ちました。精巧な説明をありがとう
srikanth

@polygenelubricants、なぜ私Predicate<Integer>たちがすでに持っているF<Integer, Boolean>のに、まったく同じことをするものを発明するのですか?
Pacerier 2014

また、Java 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;
     }
}

概念的な理解を深めるために、一次論理について読むことをお勧めします。

編集 Java 8では、Java APIで定義され
た標準のPredicateインターフェース(java.util.function.Predicate)があります。Java8より前のバージョンでは、com.google.common.base.Predicateインターフェースを再利用すると便利な場合があります。グアバ

また、Java 8以降では、ラムダを使用して述語を記述する方がはるかに簡単であることに注意してください。たとえば、Java 8以降でp -> trueは、上記のような名前付きTautologyサブクラスを定義する代わりに、関数に渡すことができます。


0

ここでJava docの例または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);

私は結果セット関連ではなく、コモンズ述語を参照していました。感謝します
srikanth

0

何まで追加マイケルは述べています:

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;
}

可能な述語の1つは次のとおりです。

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を取り除くことです。抽象化のレベルはより高く、より強力になります-しかし、手動でを実行すると、その目的が無効になり、低レベルの抽象化に戻ります。
Eugen
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.