私はいくつかのユーザーオブジェクトのリストを持っていますが、リストを並べ替えようとしていますが、メソッドリファレンスを使用してのみ動作し、ラムダ式ではコンパイラがエラーを返します:
List<User> userList = Arrays.asList(u1, u2, u3);
userList.sort(Comparator.comparing(u -> u.getName())); // works
userList.sort(Comparator.comparing(User::getName).reversed()); // works
userList.sort(Comparator.comparing(u -> u.getName()).reversed()); // Compiler error
エラー:
com\Java8\collectionapi\CollectionTest.Java:35: error: cannot find symbol
userList.sort(Comparator.comparing(u -> u.getName()).reversed());
^
symbol: method getName()
location: variable u of type Object
1 error
これは、コンパイラの型推論メカニズムの弱点です。ラムダのu
のタイプを推測するには、ラムダのターゲットタイプを確立する必要があります。これは次のように達成されます。 userList.sort()
は、タイプ_Comparator<User>
_の引数を予期しています。最初の行では、Comparator.comparing()
は_Comparator<User>
_を返す必要があります。これは、Comparator.comparing()
がFunction
引数を取るUser
を必要とすることを意味します。したがって、最初の行のラムダでは、u
はUser
型でなければならず、すべてが機能します。
2行目と3行目では、reversed()
への呼び出しが存在するため、ターゲットの入力が中断されます。理由はよくわかりません。 reversed()
のレシーバーと戻り値のタイプは両方とも_Comparator<T>
_であるため、ターゲットタイプをレシーバーに戻す必要がありますが、そうではありません。 (私が言ったように、それは弱点です。)
2行目のメソッドリファレンスは、このギャップを埋める追加の型情報を提供します。この情報は3行目にないため、コンパイラはu
がObject
(最後の手段の推論フォールバック)であると推測し、失敗します。
メソッド参照を使用できる場合は、明らかにそれを行うと動作します。追加のパラメーターを渡す場合など、メソッド参照を使用できない場合があるため、ラムダ式を使用する必要があります。その場合は、ラムダで明示的なパラメータータイプを指定します。
_userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());
_
将来のリリースでこのケースに対応するために、コンパイラーを拡張する可能性があります。
2つの引数_Comparator.comparing
_を2番目の引数としてComparator.reverseOrder()
とともに使用することにより、この制限を回避できます。
_users.sort(comparing(User::getName, reverseOrder()));
_