Comparator.reversed () non si compila usando lambda

Ho una lista con alcuni oggetti User e sto cercando di ordinare la lista, ma funziona solo usando il riferimento al metodo, con espressione lambda il compilatore dà un errore:

List 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 

Errore:

 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 

Questo è un punto debole nel meccanismo di inferenza del tipo del compilatore. Per dedurre il tipo di u nella lambda, è necessario stabilire il tipo di target per il lambda. Questo è compiuto come segue. userList.sort() si aspetta un argomento di tipo Comparator . Nella prima riga, Comparator.comparing() deve restituire il Comparator . Ciò implica che Comparator.comparing() bisogno di una Function che accetta un argomento User . Quindi nella lambda nella prima riga, devi essere di tipo User e tutto funziona.

Nella seconda e nella terza riga, la battitura di destinazione viene interrotta dalla presenza della chiamata a reversed() . Non sono del tutto sicuro del perché; sia il ricevitore che il tipo restituito di reversed() sono Comparator quindi sembra che il tipo di target debba essere propagato al ricevitore, ma non lo è. (Come ho detto, è un punto debole).

Nella seconda riga, il riferimento al metodo fornisce ulteriori informazioni sul tipo che colma questa lacuna. Questa informazione è assente dalla terza riga, quindi il compilatore deduce che u sia Object (il fallback di inferenza di ultima istanza), che fallisce.

Ovviamente se puoi usare un riferimento al metodo, fallo e funzionerà. A volte non è ansible utilizzare un riferimento al metodo, ad esempio se si desidera passare un parametro aggiuntivo, quindi è necessario utilizzare un’espressione lambda. In questo caso forniresti un tipo di parametro esplicito nel lambda:

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

Potrebbe essere ansible migliorare il compilatore per coprire questo caso in una versione futura.

È ansible aggirare questa limitazione utilizzando i due argomenti Comparator.comparing con Comparator.reverseOrder() come secondo argomento:

 users.sort(comparing(User::getName, reverseOrder()));