Java 8で導入されたラムダ式を最近習得しました。関数型インターフェイスを使用しているときはいつでも、常に実装するクラスを作成する代わりにラムダ式を使用する傾向があります。機能的なインターフェース。
これは良い習慣と考えられますか?または、機能インターフェースにLambdaを使用することが適切ではないという状況はありますか?
ラムダを使用しないことを検討すべきいくつかの基準があります。
priceIsOver100
のような名前ではありません。 x -> x.price > 100
はその名前と同じくらい明確です。条件の長いリストを置き換えるisEligibleVoter
のような名前を意味します。行き過ぎないでください。ソフトウェアは簡単に変更できることを覚えておいてください。疑問がある場合は、両方に書き、どちらが読みやすいかを確認してください。
場合によります。異なる場所で同じラムダを使用していることに気付いたときはいつでも、インターフェイスを実装するクラスの実装を検討する必要があります。しかし、匿名の内部クラスを使用した場合は、ラムダの方がはるかに優れていると思います。
私はカールビーレフェルトの答えを支持しますが、簡単な補足を提供したいと思います。
承認された カールビーレフェルトの回答 が正しいです。もう1つ区別を付けることができます。
クラス内のメソッド内にネストされたラムダコードは、そのメソッドとクラス内で見つかったすべての効果的な変数- final にアクセスできます。
関数インターフェイスを実装するクラスを作成しても、呼び出し元のコードの状態に直接アクセスすることはできません。
引用するJavaチュートリアル (私の強調)):
ローカルクラスと匿名クラスのように、ラムダ式は変数をキャプチャできます。それらは同じ外側のスコープのローカル変数へのアクセスを持っています。ただし、ローカルクラスや匿名クラスとは異なり、ラムダ式にはシャドウイングの問題はありません(詳細については、シャドウイングを参照してください)。ラムダ式はレキシカルにスコープされます。つまり、スーパータイプから名前を継承したり、新しいレベルのスコープを導入したりすることはありません。ラムダ式の宣言は、囲み環境と同じように解釈されます。
したがって、長いコードを引き出して名前を付けることには利点がありますが、それを囲んでいるメソッドとクラスの状態に直接アクセスする単純さと比較検討する必要があります。
見る:
これは一見の価値があるかもしれませんが、他の回答で行われた他のすべての優れた点に加えて、
メソッド参照を優先可能な場合。比較:
employees.stream()
.map(Employee::getName)
.forEach(System.out::println);
versus
employees.stream()
.map(employee -> employee.getName())
.forEach(employeeName -> System.out.println(employeeName));
メソッド参照を使用すると、ラムダの引数に名前を付ける必要がなくなります。これは、通常、冗長であるか、e
やx
のような遅延名につながります。
Matt McHenryの答えに基づいて、ラムダとメソッド参照の間に関係があり、ラムダを一連のメソッド参照として書き直すことができます。例えば:
employees.stream()
.forEach(employeeName -> System.out.println(employee.getName()));
対
employees.stream()
.map(Employee::getName)
.forEach(System.out::println);