Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 291
Дмитрий Киселев Avatar asked Aug 10 '15 13:08

Дмитрий Киселев


2 Answers

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.

like image 199
Tagir Valeev Avatar answered Nov 05 '22 07:11

Tagir Valeev


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.)

like image 36
Jon Skeet Avatar answered Nov 05 '22 07:11

Jon Skeet