以下の簡単な例で示すように、人々が純粋なifステートメントの代わりにPredicate
sを使用するプロジェクトをいくつか見ました。
int i = 5;
// Option 1
if (i == 5) {
// Do something
System.out.println("if statement");
}
// Option 2
Predicate<Integer> predicate = integer -> integer == 5;
if (predicate.test(i)) {
// Do something
System.out.println("predicate");
}
IfステートメントよりもPredicate
sを使用する利点は何ですか?
あなたが提供したexactの例の場合、述語を使用することは大きなやりすぎです。コンパイラーとランタイムは次のものを作成します。
- メソッド(脱糖述語)
- java.util.Predicateを実装する.class
- 2で作成されたクラスのインスタンス
これらすべてと単純なifステートメントとの比較。
そしてこれがステートレスな述語のためのすべてです。述語がステートフルの場合、次のようになります。
Predicate<Integer> p = (Integer j) -> this.isJGood(j); // you are capturing "this"
その後、この述語を使用するたびに、新しいインスタンスが作成されます(少なくとも現在のJVMの下)。
そのような述語を作成するための唯一の実行可能なオプションIMOは、もちろん、それを複数の場所で再利用することです(メソッドへの引数として渡すなど)。
述語を使用すると、コードがより柔軟になります。
常にi == 5
かどうかをチェックする条件を記述する代わりに、Predicate
を評価する条件を記述できます。これにより、さまざまなPredicate
sを渡して、さまざまな条件を実装できます。
たとえば、Predicate
は引数としてメソッドに渡すことができます。
public void someMethod (Predicate<Integer> predicate) {
if(predicate.test(i)) {
// do something
System.out.println("predicate");
}
...
}
これがfilter
のStream
メソッドの仕組みです。
Ifステートメントの使用は、バイナリ条件をチェックするための最良の(読み取り:最もパフォーマンスの高い)方法です。
Switchステートメントは、より複雑な状況ではより高速になる場合があります。
Predicate
はFunction
の特殊な形式です。実際、Java言語アーキテクトは、一般的なプリミティブ型を許可する方法に取り組んでいます。これにより、Predicate<T>
がFunction<T, boolean>
とほぼ同等になります(テスト対適用メソッド名をモジュロ化) 。
関数(またはメソッド)が1つ以上の関数を引数として取る場合、それを高次関数と呼びます。関数にbehaviourを渡していると言います。これにより、強力なAPIを作成できます。
String result = Match(arg).of(
Case(isIn("-h", "--help"), help()),
Case(isIn("-v", "--version"), version()),
Case($(), cmd -> "unknown command: " + cmd)
);
この例は、Java 8+のオブジェクト関数型プログラミングのライブラリ Javaslang から引用しています。
免責事項:私はJavaslangの作成者です。