2017-11-03 7 views
12

私はどのようにしてComparator.comparing関数の働きを理解しようとしています。私はそれを理解するための自分の比較方法を作成しました。Javaラムダからコンパレータへの変換 - 中間表現

private static <T,U extends Comparable<U>> Comparator<T> comparing(Function<T,U> f) { 
    BiFunction<T,T,Integer> bfun = (T a, T b) -> f.apply(a).compareTo(f.apply(b)); 
    return (Comparator<T>) bfun; 
} 

この関数の最後の行は例外をスローします。私は

private static <T,U extends Comparable<U>> Comparator<T> comparing(Function<T,U> f) { 
    return (T a, T b) -> f.apply(a).compareTo(f.apply(b)); 
} 

にこの機能を変更した場合

しかし、それは期待通りにうまく動作します。

ラムダをComparatorに変換できる2番目の試みが使用する中間機能インターフェイスは何ですか?

+4

ラムダが変換する型は、式がそのコンテキストからの型である必要があります。最初の例では、ラムダはそれが割り当てられている変数の型であるため、 'BiFunction'に変換する必要があります。 2番目の例では、ラムダはメソッドの戻り型であるため、 'Comparator'に変換する必要があります。 'BiFunction'と' Comparator'は同じ「形」を持っているので、同じラムダは文脈によってどちらかになることができますが、それらは異なる型であり、互いにキャストするのは失敗します。 –

+0

私はこれをdownvotingしています。品質に関するものではなく、この質問には数多くの監査があり、そのうちの3つが失敗したためです。 –

答えて

11

ラムダをコンパレータに変換できる2番目の試みが使用する中間機能インターフェイスは何ですか?

Comparatorそれ自身。

2番目の方法では、Comparatorにキャストされた中間オブジェクトではなく、Comparatorを定義しています。

この関数の最後の行は例外をスローします。

はい、そうです。

2つのクラスが機能インターフェイスであり、同じシグネチャと同じ戻り値の型を持つ類似のメソッドを持っていても、それらを同じ意味で使用できるわけではありません。


面白いトリック - あなたはBiFunction<T, T, Integer> bfunの方法applyを参照してComparator<T>を行うことができる:あなたの第二の試みで、

private static <T,U extends Comparable<U>> Comparator<T> comparing(Function<T,U> f) { 
    final BiFunction<T,T,Integer> bfun = (T a, T b) -> f.apply(a).compareTo(f.apply(b)); 
    return bfun::apply; // (a, b) -> bfun.apply(a, b); 
} 
5

中間機能インタフェースは、単にComparator<T>です:

ますコードスニペットが次のコードスニペットと同等であるため、これを見ることができます:

private static <T,U extends Comparable<U>> Comparator<T> comparing(Function<T,U> f) { 
    Comparator<T> comparator = (T a, T b) -> f.apply(a).compareTo(f.apply(b)); 
    return comparator; 
} 
関連する問題