7

私はいつも Java 6 しか使っていませんでしたが、今は Java 8 の新機能を学ぶために追いついています 。 /240166764?pgno=2

そしてそれは言います:

Java API は、java.util.function パッケージでいくつかの汎用機能インターフェースを定義します。インターフェイスの 1 つである BiFunction は、パラメーターの型が T と U で、戻り値の型が R の関数を記述します。文字列比較ラムダをその型の変数に保存できます。

BiFunction<String, String, Integer> comp 
    = (first, second) -> Integer.compare(first.length(), second.length()); 

ただし、それはソートには役立ちません。BiFunction を必要とする Arrays.sort メソッドはありません。以前に関数型プログラミング言語を使用したことがある場合は、これが興味深いことに気付くかもしれません。しかし、Java プログラマーにとってはごく自然なことです。Comparator などのインターフェイスには、指定されたパラメーターと戻り値の型を持つメソッドだけでなく、特定の目的があります。Java 8 はこのフレーバーを保持しています。ラムダ式で何かをしたい場合でも、式の目的を念頭に置いて、そのための特定の関数インターフェイスを用意する必要があります。

ただし、このスレッドを見ると: How do you assign a lambda to a variable in Java 8?

そこの質問への回答は、引用された段落があなたができないと言っていることを正確に行うことを示唆しています.

では、この記事の情報は間違っているのでしょうか、それともここで何かを読み間違えているのでしょうか?

ありがとう!

4

3 に答える 3

22

リンクされたSOの回答には、記事と矛盾するものは何もありません。

型システムの通常のルールが機能インターフェースに適用されます。

変数を として宣言すると、 は のサブタイプではないためBiFunction<String,String,Integer> bifunc、 を必要とするメソッドに渡すことはできません。Comparator<String>BiFunction<String,String,Integer>Comparator<String>

機能型がすべての通常の規則に従うという事実が、この新しい機能を最小限の混乱で追加できるようにしたものです。

Comparatoraからa を作成したい場合は、次のようBiFunctionに追加するだけです。::apply

BiFunction<String,String,Integer> bifunc = (a,b) -> 
                               Integer.compare(a.length(), b.length());

Arrays.sort(array, bifunc::apply);  
于 2015-02-05T07:25:56.887 に答える
3

この記事は、タイプのオブジェクトに基づいてソートするBiFunctionことはできませんが、いつでも使用できるという意味で正しいですComparator。でもねえ、彼らは両方とも同じ体を持つことができます. 例えば:

private static void sort(Comparator<String> ls){
        Arrays.sort(someArray, ls);
}

Comparator<String> comp = (String f1, String f2) -> Integer.compare(f1.length(), f2.length());
sort(comp);

BiFunction<String, String, Integer> func = (String f1, String f2) -> Integer.compare(f1.length(), f2.length());
sort((String f1, String f2) -> Integer.compare(f1.length(), f2.length())); //line-4

sort(func) // compiler error

上記の 4 行目では、 とまったく同じラムダを渡すことができますfunc。しかし、あなたはまだ に渡すことができませfuncsort。java8 のラムダは、いくつかのFunctionalInterfaceの実装です。機能インターフェイスは、その参照型に基づいて型を取得します。これが、初期化時の同じラムダが aBiFunctionまたはのいずれかになる方法Comparatorです。

ただし、ラムダが構築されて型が取得されると、それを変更することはできません。funcしたがって、期待する型BiFunctionをソートに渡すことはできませんComparator

于 2015-02-05T05:55:52.043 に答える
2

記事は正しいです。BiFunctionたとえば、 aを a に割り当てることはできませんComparator

そうは言っても、Brian Goetz によって書かれたこの素晴らしい記事は、この問題をうまく説明しています。

コンパイラがラムダ式に遭遇すると、最初にラムダ本体を引数リストと戻り値の型がラムダ式の型と一致するメソッドに下げます (脱糖します)。

したがって、ラムダは脱糖できますがそれはどういう意味ですか? まあ、基本的には、何らかの形でラムバに一致する新しいメソッドが作成される (可能性がある) ことを意味します。

class A {
    public void foo() {
        List<String> list = ...
        list.forEach( s -> { System.out.println(s); } );
    }
}

上記のコードは、次のようにdesugarされます。

class A {
    public void foo() {
        List<String> list = ...
        list.forEach( [lambda for lambda$1 as Consumer] );
    }

    static void lambda$1(String s) {
        System.out.println(s);
    }
}

したがって、 と の場合BiFunctionComparator. 提供されたラムダは、次の両方に割り当てることができます。

// Assign the lambda to a BiFunction
BiFunction<String, String, Integer> b1 =
        (first, second) -> Integer.compare(first.length(), second.length());

// Assign the lambda to a Comparator
Comparator<String> c1 =
        (first, second) -> Integer.compare(first.length(), second.length());

// But, once the lambda has been assigned to a type you can not reassign it
BiFunction<String, String, Integer> b2 = c1; // <-- Error

ラムダが型 (BiFunctionまたは) に割り当てられると、ラムダ式が に一致したとしても、Comparator再割り当てできないことに注意してください。

于 2015-02-05T08:02:57.763 に答える