web-dev-qa-db-ja.com

Java8の述語と関数インターフェイスの違いは何ですか?

SOに関する非常に基本的な質問かもしれませんが、Java8のPredicateFunctionインターフェースの違いは何ですか?

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を返します。唯一のことは、呼び出す方法が異なることですか?

25
NullPointer

_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()などの条件を満たすストリームから最初の要素を見つけたり、条件を満たすストリームから要素の存在を確認したい場合がありますanyMatchnoneMatchallMatchなどの特定の条件.

_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);
_
32
Aomine

この場合、違いはありません、それはあなたが適用できるものだけに関係します。したがって、たとえばallMatchPredicateを期待しているので、論理的に同じことをしても、Functionを渡すことはできません。

6
Eugene

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には、単純なチェーンをサポートするメソッドがあります。

5
Jens Bannmann

Predicatebooleantest()の結果)のみを返すことができますが、Functionは変換を行い、すべてを返すことができます(apply())。

Predicateは、条件をテストするために使用されます。

Functionは、変換を行うために使用されます。

2
ACV

本当に違いはありません。

理論的には、Predicate<T>Function<T, Boolean>の間に機能的な違いはないはずです。 Predicateは、あるタイプのオブジェクトを取り、ブール値を返す単なる関数です。 Functionは、Booleanだけでなく、任意の型を返すことができる一般化です。

Java自体の中に実装の詳細があり、それらを明確にしますが、理論的には同じである必要があります。

例は、インターフェースがPredicate<String>ではなくFunction<String, Booleanのみを受け入れることができる場合です。

1

技術的な観点から見ると、Predicate<T>は単なるTを取り込んでブールプリミティブ結果を返す関数です。ただし、使用の観点から見ると、Predicate<T>Function<T, Boolean>とはまったく異なる概念です。

Predicate<T>を使用してフィルター操作を実行します。たとえば、ストリームパイプラインで、サイズnStream<T>を取得し、Predicate<T>を使用してフィルター処理し、 n以下のサイズのストリーム。一方、ストリームパイプラインのFunction<T, Boolean>は、マッピング操作を実行してStream<T>Stream<Boolean>に変換するために使用されます。

ご覧のとおり、Predicate<T>Function<T, Boolean>は技術的には同じです(簡単にするためにラッパーBooleanを無視します)が、特定のコンテキスト(ストリームパイプラインなど)に入れると、それぞれが異なる役割を果たしているため、まったく別の話です。

1
marsouf