Comparator.reversed () ne comstack pas en utilisant lambda

J’ai une liste avec certains objects utilisateur et j’essaie de sortinger la liste, mais ne fonctionne que par référence à la méthode, avec le lambda expression le compilateur donne une erreur:

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()); // Comstackr error 

Erreur:

 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 

Ceci est une faiblesse dans le mécanisme d’inférence de type du compilateur. Afin d’inférer le type de u dans le lambda, le type de cible pour le lambda doit être établi. Ceci est accompli comme suit. userList.sort() attend un argument de type Comparator . Dans la première ligne, Comparator.comparing() doit renvoyer le Comparator . Cela implique que Comparator.comparing() besoin d’une Function prenant un argument User . Ainsi dans le lambda sur la première ligne, u devez être de type User et tout fonctionne.

Dans les deuxième et troisième lignes, la saisie de la cible est interrompue par la présence de l’appel à reversed() . Je ne suis pas tout à fait sûr pourquoi; Le récepteur et le type de retour de reversed() sont tous deux Comparator . Il semble donc que le type de cible soit propagé au récepteur, mais ce n’est pas le cas. (Comme je l’ai dit, c’est une faiblesse.)

Dans la deuxième ligne, la référence de méthode fournit des informations de type supplémentaires qui remplissent cette lacune. Cette information est absente de la troisième ligne, de sorte que le compilateur infère u comme étant Object (le retour en inférence de dernier recours), qui échoue.

Évidemment, si vous pouvez utiliser une référence de méthode, faites-le et cela fonctionnera. Parfois, vous ne pouvez pas utiliser une référence de méthode, par exemple, si vous voulez passer un paramètre supplémentaire, vous devez donc utiliser une expression lambda. Dans ce cas, vous fourniriez un type de paramètre explicite dans le lambda:

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

Il est possible que le compilateur soit amélioré pour couvrir ce cas dans une prochaine version.

Vous pouvez contourner cette limitation en utilisant le second argument Comparator.comparing à deux arguments avec Comparator.reverseOrder() :

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