SOに関する非常に基本的な質問かもしれませんが、Java8のPredicate
とFunction
インターフェースの違いは何ですか?
Predicate<String> predicateTest = (s)-> s.length() > 5;
System.out.println(predicateTest.test("Predicate"));
Function<String, Boolean> functionTest = str -> str.length()> 5;
System.out.println(functionTest.apply("Function"));
ここでの私の例では、両方ともtrue
を返します。唯一のことは、呼び出す方法が異なることですか?
Predicate<T>
_と_Function<T, R>
_の違い何よりもまず_Predicate<T>
_はstrictlyブール値関数です:
_ _ _ _ _ _ _ _
| |
T --> | predicate | --> boolean
|_ _ _ _ _ _ _|
_
これは必ずしも_Function<T, R>
_には当てはまりません:
_ _ _ _ _ _ _ _
| |
T --> | function | --> R
|_ _ _ _ _ _ _|
_
後者は、_Predicate<T>
_が有効にするのと同じタイプのオブジェクトを消費しますが、戻り型でvaryを使用できます。
Predicate<T>
_および_Function<T, R>
_の使用例_Predicate<T>
_の使用例は、T
型の引数を1つ消費してブール値を返す関数が必要な場合です。例えば要素のストリームをフィルタリングしたり、.filter(predicate).findFirst()
などの条件を満たすストリームから最初の要素を見つけたり、条件を満たすストリームから要素の存在を確認したい場合がありますanyMatch
、noneMatch
、allMatch
などの特定の条件.
_Function<T, R>
_の使用例は、タイプT
の1つの引数を消費し、タイプR
に変換する関数が必要な場合です。それはstream.map(func)
を呼び出すときかもしれません。
投稿のスニペットの例に関して、_Predicate<String>
_と_Function<String, Boolean>
_は、それらが表すものに関して同じものです。つまり、どちらもString
を取り、boolean
を返す関数を表します。ただし、前者は戻り値をboolean
からBoolean
にボックス化することを回避しますが、後者はそうではありません。
とはいえ、これは必ずしも_Predicate<String>
_を使用できる場所では必ずしも_Function<String, Boolean>
_を使用できるという意味ではなく、その逆も同様です。
例:
これはコンパイル中:
_Predicate<String> predicate = p -> p.length() == 21;
Stream<String> stream = stringList().stream().filter(predicate);
_
これはしません:
_Function<String, Boolean> function = p -> p.length() == 21;
Stream<String> stream = stringList().stream().filter(function);
_
およびその逆:
これは機能しますが:
_Function<String, Boolean> function = p -> p.length() == 21;
Stream<Boolean> stream = stringList().stream().map(function);
_
これはしません:
_Predicate<String> predicate = p -> p.length() == 21;
Stream<Boolean> stream = stringList().stream().map(predicate);
_
この場合、違いはありません、それはあなたが適用できるものだけに関係します。したがって、たとえばallMatch
はPredicate
を期待しているので、論理的に同じことをしても、Function
を渡すことはできません。
Aominèの答えは基本的な違いをカバーしています。また、2つのインターフェイスには、異なる特殊なデフォルトメソッド、つまり実装クラスで呼び出すことができるメソッドがあることを付け加えます。
Predicate<T>
_Predicate<T> and(Predicate<? super T> other)
-この述語と別の述語の短絡論理ANDを表す合成述語を返します。Predicate<T> or(Predicate<? super T> other)
-この述語と別の述語の短絡論理OR)を表す合成述語を返します。negate()
-この述語の論理否定を表す述語を返します。Function<T,R>
_<V> Function<T,V> andThen(Function<? super R,? extends V> after)
-最初にこの関数を入力に適用し、次にafter
関数を結果に適用する合成関数を返します。<V> Function<V,R> compose(Function<? super V,? extends T> before)
-最初にbefore
関数を入力に適用し、次にこの関数を結果に適用する合成関数を返します。ご覧のとおり、Predicate
には、通常のif
ステートメントで使用する演算子と同様に、複雑な条件を作成するための便利なメソッドがありますが、Function
には、単純なチェーンをサポートするメソッドがあります。
Predicate
はboolean
(test()
の結果)のみを返すことができますが、Function
は変換を行い、すべてを返すことができます(apply()
)。
Predicate
は、条件をテストするために使用されます。
Function
は、変換を行うために使用されます。
理論的には、Predicate<T>
とFunction<T, Boolean>
の間に機能的な違いはないはずです。 Predicate
は、あるタイプのオブジェクトを取り、ブール値を返す単なる関数です。 Function
は、Boolean
だけでなく、任意の型を返すことができる一般化です。
Java自体の中に実装の詳細があり、それらを明確にしますが、理論的には同じである必要があります。
例は、インターフェースがPredicate<String>
ではなくFunction<String, Boolean
のみを受け入れることができる場合です。
技術的な観点から見ると、Predicate<T>
は単なるT
を取り込んでブールプリミティブ結果を返す関数です。ただし、使用の観点から見ると、Predicate<T>
はFunction<T, Boolean>
とはまったく異なる概念です。
Predicate<T>
を使用してフィルター操作を実行します。たとえば、ストリームパイプラインで、サイズn
のStream<T>
を取得し、Predicate<T>
を使用してフィルター処理し、 n
以下のサイズのストリーム。一方、ストリームパイプラインのFunction<T, Boolean>
は、マッピング操作を実行してStream<T>
をStream<Boolean>
に変換するために使用されます。
ご覧のとおり、Predicate<T>
とFunction<T, Boolean>
は技術的には同じです(簡単にするためにラッパーBoolean
を無視します)が、特定のコンテキスト(ストリームパイプラインなど)に入れると、それぞれが異なる役割を果たしているため、まったく別の話です。