在Java中如何统计集合中元素出现次数_Java集合统计方法解析
发布时间 - 2026-01-29 00:00:00 点击率:次手动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 HashM
ap())
- 避免用
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
正确并行写法:
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
统计逻辑本身简单,但类型选择、空值处理、并发控制、基本类型适配这些点,稍不注意就会在上线后暴露问题。
# java
# 大数据
# app
# ai
# apple
# stream
# 字符串数组
# guava
# String
# Integer
# NULL
# count
# 封装
# 字符串
# int
# 循环
# 数据结构
# 泛型
# 线程
# 多线程
# map
# 并发
# 对象
# 可直接
# 单线程
# 这是
# 擦除
# 就会
# 遍历
# 用了
# 仍是
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Gemini怎么用新功能实时问答_Gemini实时问答使用【步骤】
Python正则表达式进阶教程_复杂匹配与分组替换解析
Laravel Eloquent性能优化技巧_Laravel N+1查询问题解决
如何快速登录WAP自助建站平台?
html5audio标签播放结束怎么触发事件_onended回调方法【教程】
Mybatis 中的insertOrUpdate操作
Laravel如何集成Inertia.js与Vue/React?(安装配置)
Laravel怎么写单元测试_PHPUnit在Laravel项目中的基础测试入门
Laravel怎么使用Markdown渲染文档_Laravel将Markdown内容转HTML页面展示【实战】
JavaScript如何实现倒计时_时间函数如何精确控制
头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?
独立制作一个网站多少钱,建立网站需要花多少钱?
Win11怎么更改系统语言为中文_Windows11安装语言包并设为显示语言
如何在阿里云购买域名并搭建网站?
Laravel的.env文件有什么用_Laravel环境变量配置与管理详解
米侠浏览器网页图片不显示怎么办 米侠图片加载修复
微信小程序 input输入框控件详解及实例(多种示例)
如何在建站之星网店版论坛获取技术支持?
如何为不同团队 ID 动态生成多个“认领值班”按钮
Windows10电脑怎么查看硬盘通电时间_Win10使用工具检测磁盘健康
Laravel如何为API生成Swagger或OpenAPI文档
个人网站制作流程图片大全,个人网站如何注销?
php485函数参数是什么意思_php485各参数详细说明【介绍】
php在windows下怎么调试_phpwindows环境调试操作说明【操作】
如何用AWS免费套餐快速搭建高效网站?
悟空浏览器如何设置小说背景色_悟空浏览器背景色设置【方法】
iOS UIView常见属性方法小结
如何挑选最适合建站的高性能VPS主机?
浅谈Javascript中的Label语句
详解Android中Activity的四大启动模式实验简述
香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南
如何用PHP工具快速搭建高效网站?
Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】
Laravel怎么防止CSRF攻击_Laravel CSRF保护中间件原理与实践
MySQL查询结果复制到新表的方法(更新、插入)
网站制作软件免费下载安装,有哪些免费下载的软件网站?
Laravel如何配置和使用缓存?(Redis代码示例)
今日头条AI怎样推荐抢票工具_今日头条AI抢票工具推荐算法与筛选【技巧】
原生JS获取元素集合的子元素宽度实例
html5源代码发行怎么设置权限_访问权限控制方法与实践【指南】
制作电商网页,电商供应链怎么做?
网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?
js实现获取鼠标当前的位置
Laravel如何实现登录错误次数限制_Laravel自带LoginThrottles限流配置【方法】
Laravel Vite是做什么的_Laravel前端资源打包工具Vite配置与使用
香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧
JavaScript Ajax实现异步通信
python中快速进行多个字符替换的方法小结
Laravel如何自定义错误页面(404, 500)?(代码示例)
Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】


