应使用hashmap手动计数而非collections.frequency,因其时间复杂度o(n)、避免重复遍历与空指针;注意null元素处理、自定义对象需重写equals/hashcode;众数定义需业务明确是否允许多个。

用 Collections.frequency 统计每个元素出现次数,但别直接套用
很多人一看到“找众数”就立刻想用 Collections.frequency 配合 Collections.max,结果发现性能差、重复计算多、还容易空指针。它适合小列表(Collections.frequency 每次都从头遍历整个 List,如果对 1000 个元素调用 100 次,就是 10 万次遍历。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 只在原型验证或单元测试里用,比如
Collections.frequency(list, target)快速确认某个值是否高频 - 别写成
Collections.max(list, (a, b) -> Collections.frequency(list, a) - Collections.frequency(list, b))—— 这会触发 O(n²) 行为 - 如果 list 是
null或含null元素,Collections.frequency返回 0,但不会报错,容易掩盖数据异常
用 HashMap 手动计数才是稳定解法
众数本质是频率映射的极值问题,HashMap 一次遍历完成计数 + 记录最大频次,时间复杂度 O(n),空间 O(k)(k 是去重后元素数)。Java 8+ 可用 compute 或 merge 简化逻辑,但要注意 key 的 equals/hashCode 是否可靠 —— 自定义对象没重写这两个方法的话,统计永远是 1。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 初始化
Map<t integer> countMap = new HashMap();</t>,遍历 list 时用countMap.merge(item, 1, Integer::sum) - 遍历完再扫一遍 map 找最大 value 对应的 key;如果多个 key 并列最高频,需额外逻辑决定返回第一个、全部还是抛异常
- 原始 list 含
null?HashMap允许一个nullkey,但merge会 NPE,得先判空:if (item == null) { countMap.put(null, countMap.getOrDefault(null, 0) + 1); }
用 Stream + Collectors.groupingBy 写法简洁但有陷阱
Java 8 流式写法看着干净:list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())),但实际生成的是 Map<t long></t>,后续还得转回 int、再找 max。更关键的是,它默认用 HashMap,不保证顺序;如果 list 有序且你希望返回第一个出现的众数,这个 map 无法保证键的插入顺序。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 要保持插入顺序,得用
Collectors.toMap配合LinkedHashMap::new,但代码变长,不如手动HashMap直观 -
Collectors.counting()返回Long,和int频次变量混用可能触发自动拆箱,在极端情况(超 21 亿次)才真有问题,但类型不一致本身是隐患 - 流式写法在 Android(低版本)或老 JVM(
众数不存在或不唯一时,Collections.max 不是你该依赖的工具
Collections.max 只能比较元素本身,不能比较它们的频次 —— 除非你提前把元素转成“带频次的包装类”。硬塞进去只会比较元素自然序(比如字符串字典序),和众数完全无关。网上有些示例用 max 配自定义 Comparator,但前提是已经完成频次统计,此时 max 只是“查表”动作,不是核心逻辑。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 别写
Collections.max(countMap.keySet(), (a, b) -> countMap.get(a).compareTo(countMap.get(b)))—— 这样做没问题,但countMap本身才是关键,max只是最后一步 - 如果 list 为空,所有方案都要单独处理:返回
null、抛NoSuchElementException,或约定返回 Optional.empty(),别让Collections.max去扛空集合 - 多个众数时,用
stream().filter(...).collect(Collectors.toList())比用max多扫一遍更清晰
最常被跳过的细节:众数定义本身有歧义——是“出现次数最多的那个值”,还是“出现次数最多的值的集合”?业务没明确前,别急着写死返回单个元素。










