Map.Entry.comparingByValue().reversed()的类型是什么?

10

我有一个地图条目列表

Map<String, Integer> map = new HashMap<>();
...(fill the map)...
List<Entry<String, Integer>> entries = new ArrayList<>(map.entrySet());

我希望按照这篇答案的方法根据数值对它进行排序,但要按相反的顺序排列。 当我这样做时:

Comparator<Entry<String, Integer>> cmp = Entry.comparingByValue();
entries.sort(cmp.reversed());

一切都很好。但是当我尝试将上述两行缩短为

entries.sort(Entry.comparingByValue().reversed());

编译器返回

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>

这似乎很奇怪,因为Comparator的reversed()默认方法的实现只是将其转移到Collections.reverseOrder(),我可以将上面的行更改为

entries.sort(Collections.reverseOrder(Entry.comparingByValue()));

要工作。但是Entry.comparingByValue().reversed()的正确类型是什么?

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

看起来并不起作用。省略类型参数Entry<String, Integer>是可以的,但这会导致编译器后面出现“未经检查的方法调用”警告。


3
检查这个问题的答案:https://dev59.com/qmAf5IYBdhLWcg3wUBNc - ernest_k
2个回答

19
编译器在这种情况下无法推断出泛型类型参数。你可以明确指定它们:
entries.sort(Entry.<String, Integer>comparingByValue().reversed());

问题在于你需要先知道comparingByValue返回的比较器类型,才能知道reversed返回的类型。
我没有看到任何好的理由,说明为什么一个聪明的编译器不能反向工作,并知道sort需要特定的类型,所以reversed必须是特定的类型,因此comparingByValue也必须是特定的类型。但事实并非如此。
类型推断仍在研究中(就连Java 10最近也有),所以也许在未来会有所改进。

7
当您缩短
Comparator<Entry<String, Integer>> cmp = Entry.comparingByValue();
entries.sort(cmp.reversed());

to

entries.sort(Entry.comparingByValue().reversed());

您需要删除从cmp声明中获得的类型信息。编译器仍然需要知道这些信息,因此您需要将通用类型添加到Entry中:

entries.sort(Entry.<String, Integer>comparingByValue().reversed());

哎呀,看起来我把“.”放错了位置。现在已经修复了。 - MTCoster

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