This question already has an answer here:
I have a list of map entries
Map<String, Integer> map = new HashMap<>();
...(fill the map)...
List<Entry<String, Integer>> entries = new ArrayList<>(map.entrySet());
and I want to sort it by values according to this answer, but in reverse order. When I do
Comparator<Entry<String, Integer>> cmp = Entry.comparingByValue();
entries.sort(cmp.reversed());
everything works fine. But when I try to shorten the above two lines to
entries.sort(Entry.comparingByValue().reversed());
the compiler returns
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>
This seems strange because the implementation of Comparator's reversed()
default method simply transfers it to Collections.reverseOrder()
and I can change the above line to
entries.sort(Collections.reverseOrder(Entry.comparingByValue()));
to work. But what is the correct type of Entry.comparingByValue().reversed()
?
Comparator<Entry<String, Integer>> cmp = Entry.comparingByValue().reversed();
doesn't seem to work. Omitting the type parameter Entry<String, Integer>
works, but this results in "unchecked method invocation" warning from the compiler later.
The compiler is not clever enough to infer the generic type parameters in this case. You can specify them explicitly:
entries.sort(Entry.<String, Integer>comparingByValue().reversed());
The issue is that you first need the type of the comparator returned by comparingByValue
to know the type of the one returned by reversed
.
I don't see any good reason why a clever compiler couldn't work backwards and know that sort
requires a particular type, so reversed
must be a particular type, so comparingByValue
must be a particular type. But that's not how things are.
Type inference is still being worked on (as recently as Java 10), so maybe in the future, who knows.
When you shorten down
Comparator<Entry<String, Integer>> cmp = Entry.comparingByValue();
entries.sort(cmp.reversed());
to
entries.sort(Entry.comparingByValue().reversed());
you remove the type information gleaned from cmp
’s declaration. The compiler still needs to know that information, so you need to add the generic typing to Entry
:
entries.sort(Entry.<String, Integer>comparingByValue().reversed());
.
in the wrong place. Fixed now. - MTCoster