ラムダ式とメソッドリファレンスの比較[終了]


114

IntelliJは、ラムダ式をメソッド参照に置き換えることを提案し続けます。

両者の間に客観的な違いはありますか?


4
いいえ、オブジェクトは表示されません。それは私への静的な呼び出しのように見えます
ジェラール

9
もちろん!でも「見つけられない」...好みの問題ですが、もっと技術的な面が気になりました。実際、あなたがすでに同じであるとあなたが言ったように、それは私への良い答えです。いずれにせよ、IntelliJが提案しているように、ラムダよりもメソッド参照を参照するほうが一般に高く評価されます(ただし、私には適していません)。
ジェラール

15
ラムダ式のコードは合成メソッドにコンパイルされますが、メソッド参照は機能しません(例外:などの特別な構成体Type[]::new)。実行時に生成される匿名クラスは同じです。JREはそれらの間で何の違いもありません。したがって、メソッド参照を使用すると、コンパイルされたコードで1つのメソッドを節約できます。一方、ステップバイステップのデバッグを実行するときに、それらのメソッドで停止することはできません…
Holger

6
質問は締め切られます...決定的なものがないとしても、ラムダと参照の違いを知らない私のようなすべてのユーザーにとってはあまりにも悪いです。なぜ誰もそれに答えようとはしなかったのかしら。それが私に対する正しい答えです。
Gerard

3
2年前の閉じた質問に答えることはおそらく悪い考えですが、実際に質問を読む人にとって、これはOracleのチュートリアル(docs.oracle.com/javase/tutorial/java/javaOO/…)が言うものです:メソッドの参照...はすでに名前が付けられているメソッドのコンパクトで読みやすいラムダ式。
明日

回答:


187

この機能を言語に追加した理由について、厳密にそうする必要がないことを明確にしてみましょう(すべてのメソッドrefはラムダとして表現できます)。

正解はありません。「常にラムダの代わりにメソッドリファレンスを使用する」または「常にメソッドリファレンスの代わりにラムダを使用する」と言った人は無視してください。

この質問は、「名前付きクラスと匿名クラスをいつ使用する必要があるか」と精神的に非常に似ていますか 答えは同じです読みやすくなります。確かにどちらか一方のケースは確かにありますが、真ん中には多数の灰色があり、判断が必要です。

メソッド参照の背後にある理論は単純です。名前が重要です。メソッドに名前が付いている場合、最終的にそれを反転させて呼び出すだけの必須のコードバッグではなく、名前でメソッドを参照する方が、多くの場合(常にではありませんが)より明確で読みやすいです。

パフォーマンスやキャラクターのカウントについての議論は、ほとんどがニシンであり、無視する必要があります。目標は、それが何をするのか非常に明確なコードを書くことです。ほとんどの場合(常にではありませんが!)、メソッド参照はこのメトリックで勝つため、それらをオプションとして含めて、それらのケースで使用されます。

メソッドが意図を明確にするか難読化するかに関する重要な考慮事項は、表現されている関数の形状がコンテキストから明らかであるかどうかです。場合によっては(たとえば、map(Person::getLastName)あるものを別のものにマップする関数が必要であることがコンテキストから明らかであり、このような場合、メソッド参照が有効です。他の場合では、メソッドrefを使用すると、リーダーはどのような種類かを疑問に思う必要があります。関数の説明中です;これは、ラムダが長くても読みやすくなる可能性があることを示す警告です。

最後に、ラムダよりも新しくて奇妙な感じがするため、ほとんどの人は最初はメソッド参照を避け、最初は「読みにくく」なりますが、時間が経つにつれて構文に慣れるようになることがわかりました。一般に、動作を変更し、可能な場合はメソッド参照に引き寄せます。したがって、あなた自身の主観的な最初の「読みにくい」反応は、ほぼ確実に親しみやすさの偏りを伴うことに注意してください。スタイルの意見を述べる前に、両方に慣れる機会を自分に与える必要があります。


25
@ジェラールありがとうございます。
Yassin Hajaj 2016

3
@ジェラールブライアンが「いいえ、ありません」と言っているようです
dj18

ブライアン、メソッド参照とラムダを同じメソッドに使用すると、異なる結果が得られます。それらは交換可能ではありませんか?
mFeinstein 2018年

@mFeinsteinすべてのメソッドrefには、同等のラムダがあります(これを使用してもしなくてもかまいません)。コードを質問として投稿しますか?
ブライアンゲッツ

したいのですが、コードが大きすぎるのではないかと思います。これはAndroidでLiveData、にトリガーされたFragmentに変換されたAndroidであり、Androidが同じに戻ったときに別の動作が発生します。 .so質問のために単純化するのに苦労していますEventViewModelFragment
mFeinstein

10

複数のステートメントで構成される長いラムダ式は、コードの可読性を低下させる可能性があります。そのような場合、メソッドでそれらのステートメントを抽出し、それを参照することをお勧めします。

もう1つの理由は、再利用性です。いくつかのステートメントのラムダ式をコピーして貼り付ける代わりに、メソッドを作成して、コードのさまざまな場所から呼び出すことができます。


3
比較:houses.map(House::getName)houses.map(h -> h.getName())。ラムダは2文字少なくなります。型が明示的ではないことは事実ですが、どのIDEでもわかりますし、型が明らかな場合はラムダを使用する必要があります。私は再利用性についてあなたに同意するかもしれませんが、ラムダは正確に小さいので、大きな特定のメソッドを作成する代わりにそれらを連鎖させることができます。その意味で、小さなメソッドはいくつかの大きく複雑なメソッドよりも再利用可能であり、ラムダの明快さ(そしてある程度までは冗長)のため、読みやすくなっています。
ジェラール

11
ジェラルドと一緒です。コードを移動すると読みやすさは実際に損なわれるため、読み続けるにはそのコードにジャンプし、次にジャンプする必要があります。あなたは欲しい同じ場所に関連するすべてのコードを持っています。また、House非常に害のない例です。どうかThreeStoryRedBrickHouseWithBlueDoors。私は複数引数のラムダのメソッド参照を好み、ラムダは単一のメソッド呼び出しについてのみであることを強調することもあります。メソッドを参照して間違って行くことにあまりあります:あなたは誤って外部スコープなどからの変数を参照して、使用現場で引数のスペルを間違えかもしれない
マルコTopolnik

@ジェラール私はあなたの最初の声明に同意しません。わかりやすいメソッド名を使用し、大量のコードを抽出した場合、コードを移動すると読みやすくなります。難読化メソッド名を使用している場合は、同意します。
Torsten
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.