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

Joh*_*ane 5 java generics comparator

我有一个地图条目列表

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

我想根据这个答案按值对其进行排序,但顺序相反。当我做

Comparator<Entry<String, Integer>> cmp = Entry.comparingByValue();
entries.sort(cmp.reversed());
Run Code Online (Sandbox Code Playgroud)

一切正常。但是当我尝试将上述两行缩短为

entries.sort(Entry.comparingByValue().reversed());
Run Code Online (Sandbox Code Playgroud)

编译器返回

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>
Run Code Online (Sandbox Code Playgroud)

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

entries.sort(Collections.reverseOrder(Entry.comparingByValue()));
Run Code Online (Sandbox Code Playgroud)

上班。但是什么是正确的类型Entry.comparingByValue().reversed()

Comparator<Entry<String, Integer>> cmp = Entry.comparingByValue().reversed();
Run Code Online (Sandbox Code Playgroud)

似乎不起作用。省略类型参数Entry<String, Integer>有效,但这会导致编译器稍后发出“未经检查的方法调用”警告。

Mic*_*ael 11

在这种情况下,编译器不够聪明,无法推断出泛型类型参数。您可以明确指定它们:

entries.sort(Entry.<String, Integer>comparingByValue().reversed());
Run Code Online (Sandbox Code Playgroud)

问题是您首先需要返回的比较器comparingByValue的类型才能知道返回的比较器的类型reversed

我看不出有什么好的理由说明一个聪明的编译器不能向后工作并且知道这sort需要特定类型,因此reversed必须是特定类型,因此comparingByValue必须是特定类型。但事情并非如此。

类型推断仍在进行中(就像最近的 Java 10 一样),所以也许在未来,谁知道呢。


MTC*_*ter 7

当你缩短时

\n\n
Comparator<Entry<String, Integer>> cmp = Entry.comparingByValue();\nentries.sort(cmp.reversed());\n
Run Code Online (Sandbox Code Playgroud)\n\n

\n\n
entries.sort(Entry.comparingByValue().reversed());\n
Run Code Online (Sandbox Code Playgroud)\n\n

您删除从 \xe2\x80\x99s 声明中收集的类型信息cmp。编译器仍然需要知道该信息,因此您需要将通用类型添加到Entry

\n\n
entries.sort(Entry.<String, Integer>comparingByValue().reversed());\n
Run Code Online (Sandbox Code Playgroud)\n