按反向值排序 Map<String, Long>

Sort Map<String, Long> by value reversed

我有一个 Map<String, Long> map,我想使用 Java 的功能按相反顺序按 Long 值排序 8. 使用 Google 我发现 this thread 提供了这个解决方案

Map<String, Long> sortedMap = map.entrySet().stream()
           .sorted(comparing(Entry::getValue))
                     .collect(toMap(Entry::getKey, Entry::getValue,
                              (e1,e2) -> e1, LinkedHashMap::new));

如果我想在评论中颠倒顺序,它说使用 comparing(Entry::getValue).reversed() 而不是 comparing(Entry::getValue)

但是,代码不起作用。但通过这个小小的调整,它做到了:

Map<String, Long> sortedMap = map.entrySet().stream()
          .sorted(Comparator.comparing(Entry::getValue))
                .collect(Collectors.toMap(Entry::getKey, Entry::getValue,
                      (e1, e2) -> e1, LinkedHashMap::new));

我是否必须先进行一些导入才能 运行 原始代码?

因为

还需要得到相反的顺序
Map<String, Long> sortedMap = map.entrySet().stream()
          .sorted(Comparator.comparing(Entry::getValue).reversed())
                .collect(Collectors.toMap(Entry::getKey, Entry::getValue,
                      (e1, e2) -> e1, LinkedHashMap::new));

给我一条错误信息:

The type Map.Entry does not define getValue(Object) that is applicable here

this answer 中所述,当您像 Comparator.comparing(Entry::getValue).reversed() 中那样 chain 方法调用时,Java 8 的类型推断达到了极限。

相比之下,当使用 嵌套 调用时 Collections.reverseOrder(Comparator.comparing(Entry::getValue)) 它将起作用。

当然可以用static imports:

Map<String, Long> sortedMap = map.entrySet().stream()
    .sorted(reverseOrder(comparing(Entry::getValue)))
    .collect(toMap(Entry::getKey, Entry::getValue,
          (e1, e2) -> e1, LinkedHashMap::new));

但应该注意的是,当您忘记 import static 语句(即找不到该方法)并将其与 lambda 表达式或方法引用组合时,编译器喜欢提供误导性的错误消息。


最后一点,还有现有的比较器实现 Map.Entry.comparingByValue() and Map.Entry.comparingByValue(Comparator) 允许您使用

Map<String, Long> sortedMap = map.entrySet().stream()
    .sorted(reverseOrder(comparingByValue()))
    .collect(toMap(Entry::getKey, Entry::getValue,
          (e1, e2) -> e1, LinkedHashMap::new));

Map<String, Long> sortedMap = map.entrySet().stream()
    .sorted(comparingByValue(reverseOrder()))
    .collect(toMap(Entry::getKey, Entry::getValue,
          (e1, e2) -> e1, LinkedHashMap::new));