JavaでPredicate
を使用するコードを調べています。 Predicate
を使用したことがありません。誰かがPredicate
とそのJavaでの実装のチュートリアルや概念説明に私を導くことができますか?
グアバから com.google.common.base.Predicate<T>
について話していると思います。
APIから:
指定された入力の
true
またはfalse
値を決定します。たとえば、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
テストなしではるかに簡単になったことに注意してください。 filter
を使用してPredicate
- ingでIterable<Integer> evenNumbers
を定義することにより、より高いレベルの抽象化に到達しました。
Iterables.filter
Predicate
を使用すると、Iterables.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にはファーストクラスのメソッドがありません。methodsをIterables.filter
およびIterables.all
に渡すことはできません。もちろん、Javaでobjectsを渡すことができます。したがって、Predicate
タイプが定義され、代わりにこのインターフェースを実装するobjectsを渡します。
述語は、真/偽(つまりブール値)である命題とは対照的に、真/偽(つまりブール値)を返す関数です。 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次論理について読むことをお勧めします。
編集
標準 Predicate インターフェース( Java.util.function.Predicate )Java APIのJavaで定義されています8. Java 8より前では、 com.google.common.base.Predicate インターフェース Guava 。
また、Java 8では、ラムダを使用して述語を記述する方がはるかに簡単であることに注意してください。たとえば、Java 8以降では、上記のような名前付きのTautologyサブクラスを定義する代わりに、p -> true
を関数に渡すことができます。
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;
}
可能な述語の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);