如何收集与 Java 8 中的 List 相同的最大数字键

Rem*_*emo 0 java collections java-stream

我想从 Java 8+ 中的 Map<String,Integer> 收集最大数字列表的关联键

例如:

final Map<String, Integer> map = new HashMap<>();
map.put("first", 50);
map.put("second", 10);
map.put("third", 50);
Run Code Online (Sandbox Code Playgroud)

在这里我想返回与最大值关联的键列表。

对于上面的例子,预期输出是[first,third]。因为这两个键具有相同的最大值。

我尝试使用以下方法,但只能获得单个最大密钥。

final String maxKey = map.entrySet()
    .stream()
    .max(Map.Entry.comparingByValue())
    .map(Map.Entry::getKey)
    .orElse(null);

final List<String> keysInDescending = map.entrySet()
    .stream()
    .sorted(Map.Entry.<String,Integer>comparingByValue().reversed())
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());

System.out.println(maxKey); // third
System.out.println(keysInDescending); //[third, first, second]
Run Code Online (Sandbox Code Playgroud)

但我的预期输出是[第一,第三]。在Java 8+版本中如何实现呢?

azr*_*zro 6

按值分组,给出 a Map<Integer, List<String>>,然后取最大键的值

List<String> maxKeys = map.entrySet()
        .stream()
        .collect(groupingBy(Map.Entry::getValue, mapping(Map.Entry::getKey, toList())))
        .entrySet()
        .stream()
        .max(Map.Entry.<Integer, List<String>>comparingByKey())
        .orElseThrow().getValue();
Run Code Online (Sandbox Code Playgroud)

迭代两次,但第二次地图最小


最佳性能解决方案仍然是一次迭代 for 循环

List<String> maxKeys = new ArrayList<>();
int maxValue = Integer.MIN_VALUE;

for (Map.Entry<String, Integer> e : map.entrySet()) {
    if (e.getValue() < maxValue) continue;
    if (e.getValue() > maxValue) maxKeys.clear();
    maxValue = e.getValue();
    maxKeys.add(e.getKey());
}
Run Code Online (Sandbox Code Playgroud)