最推荐用HashMap一次遍历统计频次,时间复杂度O(n);int数组注意自动装箱,String数组可直接作为key,自定义对象需重写equals()和hashCode();小数据量可用Stream API;整数范围有限时可用索引数组优化性能。

最常用也最推荐的方式是用 HashMap,一次遍历就能完成,时间复杂度 O(n),适用于任意类型数组(int、String、自定义对象等)。
用 HashMap 统计(通用可靠)
核心逻辑:以元素为 key,出现次数为 value,遍历时累加。
- 对 int 数组,注意自动装箱(
int → Integer),HashMap 可直接支持 - 对 String 数组,字符串本身可作 key,无需额外处理
- 对自定义对象(如 Person),必须重写
equals()和hashCode(),否则相同内容的对象会被当成不同 key - 推荐写法:
map.put(num, map.getOrDefault(num, 0) + 1),简洁且避免判空
用 Stream API 简化(适合小数据量)
Java 8+ 支持函数式风格,代码更紧凑,可读性高,但有轻微性能开销。
- 基本类型数组需先转为包装类型流:
Arrays.stream(arr).boxed() - String 数组可直接流式处理:
Arrays.stream(words).collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) - 返回的是
Map<K, Long>,注意 value 类型是 Long
整数范围有限时用索引数组(高效省内存)
当所有元素都是非负整数,且最大值不大(比如 0~999),可用普通数组替代 HashMap。
立即学习“Java免费学习笔记(深入)”;
- 声明长度为
maxValue + 1的int[] count - 遍历时直接用元素值作下标:
count[num]++ - 避免哈希计算和对象开销,空间换时间,特别适合计数排序场景
- 不适用于负数、大范围数或非数字类型
后续处理常见需求
统计完只是第一步,实际中常需进一步分析:
- 找最高频元素:遍历 Map entrySet,边扫边记 maxCount 和对应 key,比排序更高效
- 按频次降序排列:把 entrySet 转成 List,用
sort((a, b) -> b.getValue().compareTo(a.getValue())) - 获取前 K 高频:可用
PriorityQueue或 Stream 的limit(K) - 多线程环境:改用
ConcurrentHashMap,并确保更新操作原子(如用merge())


















