Java 8中Map.Entry比较器

14

我一直在试图使用Lambda表达式来制作Java8中的Map.Entry比较器,但发现了一个非常奇怪的行为。

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运行良好,但com2包含一个错误"无法解析方法getValue"。我真的不知道为什么?有任何建议吗?

附言:有没有避免使用Map.EntryInteger,String输入的方法? 有更短的方式吗?


这似乎是Java编译器推断lambda的泛型参数和返回类型的限制,所以在这里可能没有太多可以做的。你可以等待下一个版本的编译器,它可能会更智能。 :) - biziclop
2个回答

25
自Java-8以来,有一个独立的方法Entry.comparingByValue可用于替代:
Comparator<Map.Entry<Integer, String>> com2 = 
        Map.Entry.<Integer, String>comparingByValue().reversed();

另一种执行相同操作的方法是传递参数:

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

这种方式不需要类型参数。


14

在指定方法引用时,您目前正在指定原始类型 - 在第一种情况下,通过赋值的通用类型推断告诉编译器您的意思,但对于方法调用的目标则不起作用。 但是,您可以为方法引用指定通用类型:

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

我知道这会增加你在代码中需要使用Map.Entry<Integer, String>的次数,但不幸的是在这里很难避免。


谢谢,那肯定有效!虽然Intellij显示相同的警告。但是我能避免输入这么多Map.Entry<Integer,String>吗? - Дмитрий Киселев
1
@ДмитрийКиселев:你可能可以通过编写自己的实用方法来调用reverse,但它们在其他方面可能会很丑陋... - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接