如何在Java 8+中收集Map中最大值对应的所有键到List
Java 8+ 收集Map中所有对应最大值的键到List
方法一:两次遍历(简洁直观)
先获取Map中的最大值,再过滤出所有值等于该最大值的键,这是最容易理解和实现的方式:
final Map<String, Integer> map = new HashMap<>(); map.put("first", 50); map.put("second", 10); map.put("third", 50); // 获取最大值,处理空Map的情况 Integer maxValue = map.values().stream() .max(Integer::compareTo) .orElse(null); // 过滤所有值等于最大值的键 List<String> maxKeys = map.entrySet().stream() .filter(entry -> maxValue != null && entry.getValue().equals(maxValue)) .map(Map.Entry::getKey) .collect(Collectors.toList()); System.out.println(maxKeys); // 输出 [first, third]
如果Map为空,maxValue会是null,此时过滤后的结果是空列表,符合预期。
方法二:一次遍历(适合大数据量)
如果Map数据量很大,不想做两次遍历,可以用reduce操作在一次遍历中同时跟踪最大值和对应的键列表:
final Map<String, Integer> map = new HashMap<>(); map.put("first", 50); map.put("second", 10); map.put("third", 50); List<String> maxKeys = map.entrySet().stream() .reduce( // 初始值:空列表 + 最小整数 new AbstractMap.SimpleEntry<>(Collections.emptyList(), Integer.MIN_VALUE), (acc, entry) -> { int currentVal = entry.getValue(); if (currentVal > acc.getValue()) { // 当前值更大,更新为仅包含当前键的列表 return new AbstractMap.SimpleEntry<>(Collections.singletonList(entry.getKey()), currentVal); } else if (currentVal == acc.getValue()) { // 当前值等于最大值,添加到列表 List<String> updatedList = new ArrayList<>(acc.getKey()); updatedList.add(entry.getKey()); return new AbstractMap.SimpleEntry<>(updatedList, currentVal); } else { // 当前值更小,保留原有结果 return acc; } }, // 并行流场景下的合并逻辑:合并两个结果,取最大值对应的列表 (acc1, acc2) -> { if (acc1.getValue() > acc2.getValue()) { return acc1; } else if (acc1.getValue() < acc2.getValue()) { return acc2; } else { List<String> mergedList = new ArrayList<>(acc1.getKey()); mergedList.addAll(acc2.getKey()); return new AbstractMap.SimpleEntry<>(mergedList, acc1.getValue()); } } ) .getKey(); System.out.println(maxKeys); // 输出 [first, third]
这种方式只遍历一次Map,但代码相对复杂,适合对性能要求较高的场景。
方法三:分组后取最大组
先按值对键进行分组,再找到值最大的分组对应的键列表:
final Map<String, Integer> map = new HashMap<>(); map.put("first", 50); map.put("second", 10); map.put("third", 50); // 按值分组,key是数值,value是对应键的列表 Map<Integer, List<String>> valueGrouped = map.entrySet().stream() .collect(Collectors.groupingBy( Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList()) )); // 找到最大的数值对应的键列表 List<String> maxKeys = valueGrouped.entrySet().stream() .max(Map.Entry.comparingByKey()) .map(Map.Entry::getValue) .orElse(Collections.emptyList()); System.out.println(maxKeys); // 输出 [first, third]
这种方式逻辑清晰,适合需要多次基于值查询键的场景,但会额外创建分组Map,内存开销略大。
内容的提问来源于stack exchange,提问作者Remo
相关产品推荐
相关产品推荐

