0

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.


2 답변


3

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.


1

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());


  • Oops, looks like I put the . in the wrong place. Fixed now. - MTCoster

Linked


Related

Latest