217

注:この質問は、以前のSOの質問であったデッドリンクに由来しますが、ここに行きます...

このコードを参照してください(注:このコードは「機能」せず、使用する必要があることを知っていますInteger::compare-リンクされた質問から抽出しただけです):

final ArrayList <Integer> list 
    = IntStream.rangeClosed(1, 20).boxed().collect(Collectors.toList());

System.out.println(list.stream().max(Integer::max).get());
System.out.println(list.stream().min(Integer::min).get());

と の javadoc によると、.min()両方.max()の引数はComparator. ただし、ここではメソッド参照はIntegerクラスの静的メソッドです。

では、なぜこれがコンパイルされるのでしょうか。

4

5 に答える 5

243

ここで何が起こっているのか説明しましょう。明らかではないからです。

まず、Stream.max()のインスタンスを受け入れてComparator、ストリーム内の項目を相互に比較して、あまり気にする必要のない最適な順序で最小値または最大値を見つけられるようにします。

もちろん、問題は、なぜInteger::max受け入れられるのかということです。やっぱりコンパレーターじゃない!

その答えは、新しいラムダ機能が Java 8 で機能する方法にあります。それは、「単一抽象メソッド」インターフェース、または「SAM」インターフェースとして非公式に知られている概念に依存しています。1 つの抽象メソッドを持つ任意のインターフェイスは、メソッド シグネチャがインターフェイス上の 1 つのメソッドに一致する任意のラムダ (またはメソッド参照) によって自動的に実装できるという考えです。そのため、インターフェースを調べComparatorます(単純なバージョン):

public Comparator<T> {
    T compare(T o1, T o2);
}

メソッドが を探している場合、Comparator<Integer>基本的にこのシグネチャを探しています。

int xxx(Integer o1, Integer o2);

メソッド名はマッチングの目的で使用されないため、「xxx」を使用します。

したがって、 と の両方Integer.min(int a, int b)Integer.max(int a, int b)十分に近いため、オートボクシングによってこれがComparator<Integer>メソッド コンテキスト内の として表示されます。

于 2014-03-21T14:42:17.967 に答える