Java中用Collectors.groupingBy()配合Lambda或方法引用实现对象分组:按单字段(如Person::getCity)分组;多条件可用SimpleEntry组合键;可结合下游收集器做聚合统计;需处理null值,如过滤或设默认值。

Java 中用 Lambda 表达式实现对象分组,核心是借助 Collectors.groupingBy() 配合方法引用或 Lambda 作为分类函数。
用 groupingBy 按单个字段分组
最常见场景:按对象的某个属性(如字符串、数字)分组。假设有一个 Person 类:
class Person {
String name;
int age;
String city;
// 构造器、getter 省略
}
按城市分组,生成 Map<string list>></string>:
List<person> people = ...;
Map<string list>> byCity = people.stream()
.collect(Collectors.groupingBy(Person::getCity));</string></person>
这里 Person::getCity 是方法引用,等价于 p -> p.getCity()。
按多个条件分组(组合键)
Java 没有内置元组,可用匿名类、AbstractMap.SimpleEntry 或自定义键类。推荐用 SimpleEntry 快速组合:
- 按城市 + 年龄段(如“20-30”)分组:
Map<abstractmap.simpleentry string>, List<person>> grouped = people.stream()
.collect(Collectors.groupingBy(p ->
new AbstractMap.SimpleEntry(
p.getCity(),
p.getAge() </person></abstractmap.simpleentry>
注意:SimpleEntry 的 equals/hashCode 基于 key 和 value,适合做分组键。
将后端 Java 接口文档转换为前端 TypeScript 类型定义(interface / type)。输入:飞书文档、Spring Boot 接口文档、Swagger/OpenAPI、手写 API 文档等。输出:包含请求参数与响应结果的 .md 文件,含完整 JSDoc 注释。触发关键词:Java 转 TS、接口转换、生成前端类型、接口文档转 TypeScript、DTO/VO/BO 转 interface、后端文档转前端类型、生成接口类型、类型定义生成。
分组后做聚合(如统计数量、求平均年龄)
用 groupingBy 的重载方法,传入下游收集器:
- 统计每座城市人数:
Collectors.counting() - 计算每座城市平均年龄:
Collectors.averagingInt(Person::getAge) - 只取每组第一个名字:
Collectors.mapping(Person::getName, Collectors.toList())
示例:
Map<string double> avgAgeByCity = people.stream()
.collect(Collectors.groupingBy(
Person::getCity,
Collectors.averagingInt(Person::getAge)
));</string>
处理 null 值和空集合
如果分组字段可能为 null,默认会抛 NullPointerException。安全做法是先过滤或提供默认值:
// 方案一:过滤掉 null 城市
Map<string list>> safeGroup = people.stream()
.filter(p -> p.getCity() != null)
.collect(Collectors.groupingBy(Person::getCity));
// 方案二:用 null-safe 分类函数
Map<string list>> withNullKey = people.stream()
.collect(Collectors.groupingBy(p -> Optional.ofNullable(p.getCity()).orElse("Unknown")));</string></string>
这样 "Unknown" 就会成为一组的 key。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










