Collectors.groupingBy 配合 Collectors.summarizingInt 可按字段分组并对整型字段统计计数、求和、平均、最值;示例为按部门统计员工年龄分布,结果返回 Map,含 getCount()、getSum() 等方法。

用 Collectors.groupingBy 配合 Collectors.summarizingInt,可以一次性按某字段分组,并对另一整型字段做统计(计数、求和、平均、最值),特别适合分析变量分布特征,比如“各年级学生的平均分、最高分、总分”。
基础写法:分组 + 整型汇总
核心是嵌套两个收集器:外层 groupingBy 指定分组键,内层 summarizingInt 指定待统计的 int 值提取逻辑。
示例:统计每个部门员工年龄的分布情况
List<Employee> employees = ...;
Map<String, IntSummaryStatistics> deptAgeStats = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment, // 分组键:部门名
Collectors.summarizingInt(Employee::getAge) // 统计值:年龄(int)
));
结果中每个部门对应一个 IntSummaryStatistics 对象,含 getCount()、getSum()、getAverage()、getMin()、getMax() 等方法。
常用分布分析场景
- 频次+集中趋势:如“每种商品销量的订单数、总销量、平均单笔销量”,直接反映分布密集度与典型值
- 分层对比:如“不同用户等级(VIP/普通)的充值金额统计”,快速识别高价值群体特征
-
异常探测辅助:结合
getMin()/getMax()与getAverage()差距,初步判断是否存在极端值或偏态分布
进阶技巧:定制统计逻辑
summarizingInt 只接受 ToIntFunction,若需统计非 int 字段(如 double 或计算值),可先映射再统计:
- 统计
double类型(如分数)→ 改用summarizingDouble - 统计“年龄平方”这类衍生值 → 用 lambda 匿名计算:
e -> e.getAge() * e.getAge() - 过滤后再统计(如只统计在职员工年龄)→ 先
filter再collect,避免在summarizingInt里判空
注意事项
- 空集合分组时,对应 key 的
IntSummaryStatistics仍存在,getCount()为 0,getAverage()返回0.0(不是NaN) - 若分组键为
null,默认会放入 map 的nullkey 中;如需排除,提前filter(e -> e.getDepartment() != null) - 不支持并发收集(
toConcurrentMap不兼容summarizingInt),多线程需用parallelStream()+ 保证线程安全的 collector,或改用groupingByConcurrent配合自定义累加器

















