/ Align = "left" / reversed () nie kompiluje się przy użyciu lambda

Mam listę z niektórymi obiektami użytkownika i próbuję posortować listę, ale działa tylko przy użyciu referencji metody, z wyrażeniem lambda kompilator daje błąd:

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

Błąd:

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
Author: Oliv, 2014-08-07

2 answers

Jest to słabość mechanizmu wnioskowania typu kompilatora. Aby wywnioskować typ u w Lambda, należy ustalić docelowy Typ dla lambda. Odbywa się to w następujący sposób. userList.sort() oczekuje argumentu typu Comparator<User>. W pierwszej linii Comparator.comparing() musi zwrócić Comparator<User>. Oznacza to, że Comparator.comparing() potrzebuje Function, który wymaga User argumentu. Tak więc w lambdzie na pierwszej linii u musi być typu User i wszystko działa.

W druga i trzecia linia, typowanie celu jest zakłócane przez obecność wywołania do reversed(). Nie jestem do końca pewien, dlaczego; zarówno odbiornik, jak i typ powrotu reversed()Comparator<T>, więc wydaje się, że typ docelowy powinien być propagowany z powrotem do odbiornika, ale tak nie jest. (jak powiedziałem, to słabość.)

W drugiej linii odniesienie do metody zawiera dodatkowe informacje o typie, które wypełniają tę lukę. Ta informacja jest nieobecna w trzeciej linii, więc kompilator wnioskuje, że u jest Object (wnioskowanie awaryjne ostateczności), które się nie udaje.

Oczywiście, jeśli możesz użyć odniesienia do metody, zrób to, a to zadziała. Czasami nie można użyć referencji metody, na przykład, jeśli chcesz przekazać dodatkowy parametr, więc musisz użyć wyrażenia lambda. W takim przypadku należy podać jawny typ parametru w Lambda:

userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());

Możliwe, że kompilator zostanie ulepszony, aby objąć ten przypadek w przyszłym wydaniu.

 87
Author: Stuart Marks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-07 03:23:37

Możesz obejść to ograniczenie używając dwóch argumentów Comparator.comparing z Comparator.reverseOrder() jako drugim argumentem:

users.sort(comparing(User::getName, reverseOrder()));
 65
Author: Misha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-06 17:58:19