2016-04-22 7 views
8

だから最も簡単な方法は、直接入力述語であり、私はストリーム上でいくつかのランダムなフィルタを使用すると仮定し述語または関数をJavaストリームフィルタとして使用する違いは何ですか?</p> <pre><code>x.stream().filter(e -> e % 2 == 0) </code></pre> <p>だけでなく、私は単純に参照を作成し、事前に述語を定義することができます:

Predicate<Integer> isEven = e -> e % 2 == 0; 
... 
x.stream().filter(isEven) 

しかし、私は、同様の機能を使用することができます。

private static boolean isEven(Integer integer) { 
    return integer % 2 == 0; 
} 
... 
x.stream().filter(MyClass::isEven) 

は、私の知る限り、述語はもちろん、はるかに限ら中です機能は副作用などがあるかもしれません。しかし、Venkat Subramaniamのような人々は後者のソリューションを使用するので、私は本当に疑問に思っています:ここでの主な違いは何ですか?

答えて

11

いいえ!述語はメソッド参照に比べて実際には制限されていません!実際、これらはすべて同じです!

だけfilter()関数のシグネチャを見て: filter(Predicate<? super T> predicate)

とのあなたの例を考えてみましょう:

x.stream().filter(e -> e % 2 == 0)

Predicate<Integer> isEven = e -> e % 2 == 0; 
... 
x.stream().filter(isEven) 

最初のものは後者のほんのインラインバージョンです。

private static boolean isEven(Integer integer) { 
return integer % 2 == 0; 
} 
... 
x.stream().filter(MyClass::isEven) 

ここでは、実際にはMethod Referencesが表示されます。 MRは、既存の関数に基づいてラムダ式を定義することを可能にする文法的な砂糖です。

これらのすべての式は、述語機能インタフェースと同じ実装になります。

また、あなたが右側のブロック構文を使用して、ラムダ式に副作用をも行うことができますが、それは一般的に勧めていない:

e -> { 
    //side effects here 
    return e % 2 == 0; 
} 
+0

私は、MRなしでは、再利用性に関して実際に制限されている述語のみを定義することができます。だから、これはきれいな書き込み方法は何ですか? MR、述語または実際のステートメント自体を使用していますか? – AdHominem

+1

@AdHominemそれはあなたの文脈によって異なります。あなたが本当に述語を再利用するつもりでないなら、単純なラムダ式に固執してください。しかし、それを再利用し続けるつもりなら、メソッド自体を作成せずにいくつかのutilsクラスで静的な述語インスタンスを作成することをお勧めします –

4

ライブラリを構築する観点から、それを見たときブール値を返す関数のライブラリは、静的な最終的な述語インスタンスのライブラリよりはるかに汎用的な述語のコレクションです。どうして?ライブラリ関数がうまく命名されている場合、彼らはより良い読み

public static final Predicate<Integer> IS_EVEN = i -> i % 2 == 0; 
  • public static boolean isEven(int i) { return i -> i % 2 == 0; } 
    

    対:

    には、以下が含まれているライブラリを考えてみましょう。久しぶりコードを再訪すると、それはfilter(i -> i % 2 == 0)よりfilter(MyLib::isEven)filter(MyLib::isEven)filter(MyLib.IS_EVEN)は、あなたは自分のライブラリ関数を呼び出す代わりに、述語としてそれを使用したくない
  • ない場合は一方で、それはより多くのだ、呼び出されている正確に何を説明しますをスキャンする方が簡単です読める。より良いMyLib.IS_EVEN.test(i)
  • よりMyLib.isEven(i)スキャンあなたはちょうどMyLib::isEvenをし続けるライブラリ関数で、IntPredicate代わりのPredicate<Integer>などグアバPredicate<Integer>、ApacheのCollections4 Predicate<Integer>を、使用する必要がある場合。 static final Predicate<Integer>インスタンスを使用すると、MyLib.IS_EVEN::testを行うことによってそれを変換しなければならない(そして、あなたはとにかくメソッド参照を使用して終了)同じ理由で、すべての機能タイプに適用され

。関数を書く。それらは、単純なメソッド参照でシグネチャと一致する任意の機能型に適用できます。

関連する問題

 関連する問題