collectors.counting()需配合groupingby实现分组计数,语法为groupingby(keymapper, counting()),返回map;处理null时默认归入一组,可filter预处理;替代方案tomap更灵活但复杂。

Java Stream API 中的 Collectors.counting() 本身不直接支持分组统计,它只是一个“计数器”,必须配合 Collectors.groupingBy() 才能实现按条件分组并统计每组元素数量。
用 groupingBy + counting 实现分组计数
这是最常用、最直观的方式:以某个属性为分类键,对流中元素分组,再对每组内元素数量进行统计。
-
语法结构:
Collectors.groupingBy(keyMapper, Collectors.counting()) - keyMapper 是一个 Function,用于从每个元素提取分组依据(如 String、Integer、枚举等)
- 返回类型是
Map<k long></k>,其中 K 是分组键类型,Long 是该组元素个数
例如,统计员工按部门划分的人数:
List<employee> employees = Arrays.asList(
new Employee("Alice", "Engineering"),
new Employee("Bob", "Marketing"),
new Employee("Charlie", "Engineering")
);
Map<string long> deptCount = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment, Collectors.counting()));
// 结果:{Engineering=2, Marketing=1}
</string></employee>
处理 null 值时需谨慎
如果 keyMapper 返回 null,groupingBy 默认使用 HashMap,而 HashMap 允许一个 null 键 —— 这意味着所有 key 为 null 的元素会被归入同一组。
- 若业务允许 null 分组,无需额外操作
- 若想跳过 null 或抛异常,可先 filter:
.filter(emp -> emp.getDepartment() != null) - 也可自定义 map factory 配合 ConcurrentMap 等,但日常场景较少需要
替代方案:用 toMap + mergeFunction(更灵活但稍复杂)
当需要定制化行为(比如遇到重复 key 时做不同合并逻辑),可用 Collectors.toMap() 替代:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- keyMapper 提取分组键
- valueMapper 固定返回 1L(表示单个元素)
- mergeFunction 定义冲突时如何累加:
(v1, v2) -> v1 + v2
示例:
Map<string long> deptCount = employees.stream()
.collect(Collectors.toMap(
Employee::getDepartment,
e -> 1L,
(v1, v2) -> v1 + v2
));
</string>
效果与 groupingBy + counting 相同,但更适合需要干预合并过程的场景(如加权计数、去重后计数等)。
注意 counting 是无状态的终端操作
Collectors.counting() 内部只是调用 summingLong(e -> 1L),它不保留元素本身,只累计数量。因此:
- 不能和
mapping()或filtering()组合用于“带条件计数”——那得换用filtering + counting或手动 map-reduce - 若还需获取每组的具体元素列表,应改用
groupingBy(Function.identity()),再对 value list 调用 size()
不复杂但容易忽略细节,关键是把 counting 放在 groupingBy 的下游收集器位置,而不是单独使用。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










