如何通过Java Streams获取HashMap中第二高值的所有键值对?
使用Java Streams获取Map中第二高值的所有键值对
你的原代码仅能获取单个第二高值的键值对,原因是skip(1).findFirst()只取了排序后的第二个元素,若存在多个值等于第二高的元素,就会遗漏。以下是能获取所有符合条件键值对的解决方案:
方法一:分步获取最大值与第二高值,再过滤收集
import java.util.*; import java.util.stream.Collectors; public class SecondHighestMapValues { public static void main(String[] args) { HashMap<String, Integer> map = new HashMap<>(); map.put("Pankaj", 1); map.put("Amit", 8); // 覆盖之前的2值 map.put("Rahul", 5); map.put("Chetan", 7); map.put("Vinod", 6); map.put("Rajesh", 7); // 1. 获取Map中的最大值 Optional<Integer> maxVal = map.values().stream() .max(Integer::compareTo); if (maxVal.isPresent()) { // 2. 获取第二高值:所有小于最大值的元素中的最大值 Optional<Integer> secondMaxVal = map.values().stream() .filter(val -> val < maxVal.get()) .max(Integer::compareTo); if (secondMaxVal.isPresent()) { // 3. 收集所有值等于第二高值的键值对 List<Map.Entry<String, Integer>> secondMaxEntries = map.entrySet().stream() .filter(entry -> entry.getValue().equals(secondMaxVal.get())) .collect(Collectors.toList()); // 输出结果 System.out.println("第二高值为:" + secondMaxVal.get()); System.out.println("对应的键值对:"); secondMaxEntries.forEach(entry -> System.out.println(entry.getKey() + ": " + entry.getValue())); } else { System.out.println("没有第二高值(所有元素值相同)"); } } else { System.out.println("Map为空"); } } }
方法二:按值分组后排序取值
通过将元素按值分组,利用TreeMap自动逆序排序的特性,直接获取第二高值对应的分组:
import java.util.*; import java.util.stream.Collectors; public class SecondHighestMapValues { public static void main(String[] args) { HashMap<String, Integer> map = new HashMap<>(); map.put("Pankaj", 1); map.put("Amit", 8); map.put("Rahul", 5); map.put("Chetan", 7); map.put("Vinod", 6); map.put("Rajesh", 7); // 按值分组,键为数值(逆序排序),值为对应键值对的列表 TreeMap<Integer, List<Map.Entry<String, Integer>>> sortedGroups = map.entrySet().stream() .collect(Collectors.groupingBy( Map.Entry::getValue, () -> new TreeMap<>(Collections.reverseOrder()), Collectors.toList() )); // 跳过最大值分组,获取第二高值的分组 Optional<List<Map.Entry<String, Integer>>> secondMaxEntries = sortedGroups.values().stream() .skip(1) .findFirst(); secondMaxEntries.ifPresentOrElse(entries -> { System.out.println("第二高值为:" + entries.get(0).getValue()); System.out.println("对应的键值对:"); entries.forEach(entry -> System.out.println(entry.getKey() + ": " + entry.getValue())); }, () -> { System.out.println("没有第二高值(所有元素值相同或Map为空)"); }); } }
说明
- 方法一逻辑清晰,分步处理,适合理解基础流操作;
- 方法二利用
TreeMap的排序特性,代码更简洁高效; - 两种方法都处理了Map为空、所有元素值相同的边界场景。
内容的提问来源于stack exchange,提问作者user4711383
相关产品推荐
相关产品推荐

