10 votes

Quel est le type de Map.Entry.comparingByValue().reversed() ?

J'ai une liste d'entrées de cartes

Map<String, Integer> map = new HashMap<>();
...(fill the map)...
List<Entry<String, Integer>> entries = new ArrayList<>(map.entrySet());

et je veux le trier par valeurs en fonction de cette réponse mais dans l'ordre inverse. Quand je fais

Comparator<Entry<String, Integer>> cmp = Entry.comparingByValue();
entries.sort(cmp.reversed());

tout fonctionne bien. Mais lorsque j'essaie de raccourcir les deux lignes ci-dessus en

entries.sort(Entry.comparingByValue().reversed());

le compilateur retourne

error: incompatible types: Comparator<Entry<Object,V>> cannot be converted to Comparator<? super Entry<String,Integer>>
        entries.sort(Entry.comparingByValue().reversed());
  where V is a type-variable:
    V extends Comparable<? super V>

Cela semble étrange parce que l'implémentation de la fonction reversed() La méthode par défaut le transfère simplement à Collections.reverseOrder() et je peux changer la ligne ci-dessus en

entries.sort(Collections.reverseOrder(Entry.comparingByValue()));

pour travailler. Mais quel est le bon type de Entry.comparingByValue().reversed() ?

Comparator<Entry<String, Integer>> cmp = Entry.comparingByValue().reversed();

ne semble pas fonctionner. Omettre le paramètre de type Entry<String, Integer> fonctionne, mais cela entraîne un avertissement du compilateur "unchecked method invocation" par la suite.

19voto

Michael Points 20266

Le compilateur n'est pas assez intelligent pour déduire les paramètres du type générique dans ce cas. Vous pouvez les spécifier explicitement :

entries.sort(Entry.<String, Integer>comparingByValue().reversed());

Le problème est que vous devez d'abord connaître le type du comparateur renvoyé par la fonction comparingByValue pour connaître le type de celui retourné par reversed .

Je ne vois pas pourquoi un compilateur intelligent ne pourrait pas travailler à rebours et savoir que sort nécessite un type particulier, donc reversed doit être d'un type particulier, donc comparingByValue doit être d'un type particulier. Mais ce n'est pas comme ça que les choses se passent.

L'inférence de type fait encore l'objet de travaux ( aussi récemment que Java 10 ), donc peut-être à l'avenir, qui sait.

7voto

MTCoster Points 528

Quand vous raccourcissez

Comparator<Entry<String, Integer>> cmp = Entry.comparingByValue();
entries.sort(cmp.reversed());

à

entries.sort(Entry.comparingByValue().reversed());

vous supprimez les informations de type glanées à partir de cmp La déclaration de la Commission. Le compilateur a toujours besoin de connaître cette information, et vous devez donc ajouter le typage générique à l'élément Entry :

entries.sort(Entry.<String, Integer>comparingByValue().reversed());

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X