Java 8 Map.Entry comparator

I've been trying to make Map.Entry Comparator in Java8 using lambda expressions and have found a very strange behaviour.

Map<Integer, String> map = new TreeMap<>();

map.put(1, "Hello");
map.put(3, "zzzz");
map.put(2, "aaaa");
map.put(5, "AAAAA");
map.put(4, "aaaa");

Comparator<Map.Entry<Integer, String>> com = Comparator.comparing(Map.Entry::getValue);
com = com.reversed();

Comparator<Map.Entry<Integer, String>> com2 = Comparator.comparing(Map.Entry::getValue).reversed();

com works just fine, but com2 contains a misstake "cannot resolve method getValue". And I really don't know why? Any suggestions?

P.S. Is there any way to avoid typing Map.Entry with Integer, String? Any shorter way?

Upvotes: 14

Views: 3727

Answers (2)

Tagir Valeev
Tagir Valeev

Reputation: 100239

Since Java-8 there's a standalone method Entry.comparingByValue which can be used instead:

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

An alternative way to do the same is to pass the parameter:

Comparator<Map.Entry<Integer, String>> com2 = 
        Map.Entry.comparingByValue(Comparator.reverseOrder());

This way type arguments are unnecessary.

Upvotes: 25

Jon Skeet
Jon Skeet

Reputation: 1500913

Currently you're specifying the raw type when you specify the method reference - in the first case generic type inference with the assignment tells the compiler what you mean, but that doesn't work for the target of a method call. You can specify the generic type for the method reference though:

Comparator<Map.Entry<Integer, String>> com2 = 
    Comparator.comparing(Map.Entry<Integer,String>::getValue).reversed();

(I realize that's increasing the number of times you need Map.Entry<Integer, String> in your code, but unfortunately that's hard to avoid here.)

Upvotes: 14

Related Questions