java stream api 通过 collectors.groupingby() 实现集合分组,支持单级/多级分组、下游聚合(如计数、平均值、极值)、自定义分类逻辑、空值处理及并发安全分组。

Java Stream API 提供了简洁、函数式的方式来对对象集合进行分组,核心是 Collectors.groupingBy() 方法。它能将流中元素按指定条件归类为 Map
基础分组:按单一字段分类
最常见场景是按对象的某个属性(如字符串、数字)分组。需传入一个分类函数(Function),返回分组键:
- 假设有一个 List
,按 gender 字段分组: - Map
> byGender = people.stream().collect(Collectors.groupingBy(Person::getGender)); - 注意:若某 key 对应空列表(如无人为 "OTHER"),该 key 仍会存在于结果 Map 中;若想跳过 null 值,可先用 filter(Objects::nonNull) 预处理。
分组后聚合:统计、求和、取极值
groupingBy 支持第二个参数——下游收集器(downstream collector),用于对每个分组内的元素进一步处理:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 统计每个性别的人数:Map
countByGender = people.stream().collect(Collectors.groupingBy(Person::getGender, Collectors.counting())); - 计算各年龄段平均年龄:Map
avgAgeByAgeGroup = people.stream().collect(Collectors.groupingBy(p -> p.getAge() / 10 * 10, Collectors.averagingDouble(Person::getAge))); - 获取每组最高分:Map
> topByDept = people.stream().collect(Collectors.groupingBy(Person::getDepartment, Collectors.maxBy(Comparator.comparing(Person::getScore))));
多级分组与嵌套结构
通过组合 groupingBy 可实现类似 SQL 中 GROUP BY a, b 的效果,生成嵌套 Map:
- 先按部门分组,再在每个部门内按性别细分:Map
>> nested = people.stream().collect(Collectors.groupingBy(Person::getDepartment, Collectors.groupingBy(Person::getGender))); - 若需更灵活控制(如跳过空值、使用 LinkedHashMap 保持插入顺序),可显式传入 mapFactory 参数:Collectors.groupingBy(..., LinkedHashMap::new, ...)
自定义分组逻辑与异常处理
当分组依据非简单 getter,或需容错时,可编写带业务逻辑的分类函数:
- 按成绩等级分组(A/B/C/D):people.stream().collect(Collectors.groupingBy(p -> { int s = p.getScore(); return s >= 90 ? "A" : s >= 80 ? "B" : s >= 70 ? "C" : "D"; }))
- 避免 NPE:分类函数中主动判空,例如 p -> Optional.ofNullable(p.getDepartment()).orElse("UNKNOWN")
- 如需并发安全分组(大数据量且无状态),可用 Collectors.groupingByConcurrent(),返回 ConcurrentHashMap。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










