手动Map计数最通用:单线程用HashMap,多线程用ConcurrentHashMap;键需正确实现equals/hashCode;避免get(key)==null判空,改用containsKey;Stream.groupingBy简洁但性能略低,并行需显式指定ConcurrentHashMap;Guava Multiset语义清晰但需权衡依赖;基本类型数组统计须用IntStream避免Arrays.asList陷阱。

用 Map 手动计数最通用,但要注意键类型和线程安全
Java 没有内置的「一键统计频次」方法,最稳妥的方式是遍历集合,用 Map 累加。关键点在于:键必须是元素的 equals() + hashCode() 正确实现;若在多线程环境中操作,不能直接用 HashMap。
-
String、Integer等 JDK 内置类型可直接作键,自定义类需重写equals()和hashCode() - 单线程场景推荐
HashMap;并发场景优先选ConcurrentHashMap,或用Collections.synchronizedMap(new HashMap()) - 避免用
get(key) == null判断是否存在——null值本身可能合法,应改用containsKey(key)
示例:
MapcountMap = new HashMap<>(); for (String s : list) { countMap.put(s, countMap.getOrDefault(s, 0) + 1); }
Java 8 的 Stream.collect() 写法简洁,但别滥用
用 Collectors.groupingBy() + Collectors.counting() 可一行完成统计,代码干净,但背后是新建对象、装箱拆箱、多次函数调用,小数据量无感,高频或大数据量时性能略逊于手动 Map 循环。
- 必须注意返回类型是
Map,不是Integer,对整数计数后要转类型需额外处理 - 若集合为
null,会直接抛NullPointerException,调用前务必判空 - 不支持并行流自动线程安全——即使用了
parallelStream(),groupingBy()默认仍用HashMap,并发写会出错;如需并行,显式传入ConcurrentHashMap::new作为 map factory
正确并行写法:
立即学习“Java免费学习笔记(深入)”;
Mapcounts = list.parallelStream() .collect(Collectors.groupingBy( Function.identity(), ConcurrentHashMap::new, Collectors.counting() ));
第三方库如 Guava 的 Multiset 更语义化,但引入依赖要权衡
Multiset 是专为计数设计的数据结构,add() 即计数,count(element) 直接查频次,语义清晰、API 直观,且默认线程不安全(符合多数场景),内部优化了存储效率。
- Guava 的
HashMultiset底层仍是HashMap,但封装了计数逻辑,省去手动getOrDefault的样板代码 - 不适用于需要保持插入顺序或排序的场景——
TreeMultiset支持排序,但比较器需与元素自然顺序一致,否则行为难预测 - 如果项目已用 Guava,值得用;如果只是为计数单独引入,建议优先用 JDK 原生方案
示例:
Multisetmultiset = HashMultiset.create(list); int count = multiset.count("apple"); // 返回 int,非 Long
Arrays.asList().stream() 统计数组时容易忽略类型擦除陷阱
对基本类型数组(如 int[])直接用 Arrays.asList(arr),结果是包含一个 int[] 对象的单元素列表,而非预期的整数列表——这是泛型擦除+数组特殊性导致的经典坑。
- 正确做法:用
IntStream.of(arr)转为流,再boxed()成Integer流,最后 collect -
字符串数组无此问题:
Arrays.asList(strArray)可直接用 - 若坚持用
Arrays.asList()处理基本类型数组,必须先手动包装成对象数组(如Integer[]),否则统计结果永远是 1
错误示范(看似正常,实则无效):
int[] nums = {1, 2, 2, 3};
List list = Arrays.asList(nums); // list.size() == 1
统计逻辑本身简单,但类型选择、空值处理、并发控制、基本类型适配这些点,稍不注意就会在上线后暴露问题。










