如何用Java Streams获取存在多个众数时的所有众数?
没问题,咱们完全可以微调你现有的代码,实现返回包含所有众数(出现次数最多的元素,不管有几个)的列表或数组。核心思路是先找出元素的最大出现次数,再筛选出所有达到这个次数的元素,而不是只取第一个。
实现方案
我分两种写法给你展示,一种是链式调用的紧凑写法,另一种是分步拆解的清晰写法,你可以根据需求选择:
1. 链式调用(返回List<Integer>)
List<Integer> modes = list.stream() // 保留你原来的TreeMap来保证元素按键的自然顺序排序,也可以换成HashMap提升性能 .collect(Collectors.groupingBy(i -> i, TreeMap::new, Collectors.counting())) .entrySet().stream() // 先收集所有统计结果,再计算最大次数并筛选众数 .collect(Collectors.collectingAndThen( Collectors.toList(), entries -> { // 获取最大出现次数,空列表时返回0 long maxCount = entries.stream() .mapToLong(Map.Entry::getValue) .max() .orElse(0); // 筛选出所有出现次数等于最大值的元素 return entries.stream() .filter(entry -> entry.getValue() == maxCount) .map(Map.Entry::getKey) .collect(Collectors.toList()); } ));
2. 分步拆解(更易读,可转Integer[])
如果觉得链式调用太绕,分步写会更清晰,还能方便转成数组:
// 第一步:统计每个元素的出现次数 Map<Integer, Long> countMap = list.stream() .collect(Collectors.groupingBy(i -> i, TreeMap::new, Collectors.counting())); // 第二步:找出最大的出现次数 long maxCount = countMap.values().stream() .mapToLong(Long::longValue) .max() .orElse(0); // 处理空列表的情况 // 第三步:筛选出所有众数并收集为List List<Integer> modesList = countMap.entrySet().stream() .filter(entry -> entry.getValue() == maxCount) .map(Map.Entry::getKey) .collect(Collectors.toList()); // 转成Integer数组(如果需要) Integer[] modesArray = modesList.toArray(new Integer[0]);
关键调整说明
- 原来的代码是通过排序后取第一个元素,现在我们先计算最大出现次数,再把所有次数等于这个最大值的元素都筛选出来
- 保留了你原来的
TreeMap,所以最终的众数列表会按键的自然升序排列(和你原来代码中“次数相同时返回第一个(键最小的)”的逻辑保持一致) - 处理了空列表的边界情况,此时会返回空的列表/数组,符合预期
内容的提问来源于stack exchange,提问作者releseabe
相关产品推荐
相关产品推荐

