
本文详解如何利用 Java 8+ 的 Stream API 和 Collectors.groupingBy,基于多个字段(如 id、name、age)对对象列表进行分组,并聚合关联字段(如 job)为 List。
本文详解如何利用 java 8+ 的 stream api 和 collectors.groupingby,基于多个字段(如 id、name、age)对对象列表进行分组,并聚合关联字段(如 job)为 list
在实际开发中,常需将具有相同业务主键(非单一字段)的对象列表按多维度归并,例如将同一人(id + name + age 共同唯一标识)的所有岗位合并为一个集合。Java Stream 提供了简洁高效的解决方案,核心在于构造合适的分组键(grouping key)。
✅ 推荐方案:使用复合键 Record(Java 14+)
最清晰、安全且符合现代 Java 实践的方式是定义一个不可变的复合键 record,覆盖 equals() 和 hashCode()(record 默认已实现,但需确保所有参与分组的字段都包含在 record 中):
record PersonKey(long id, String name, int age) {}
然后将原始数据建模为包含该键和待聚合字段的类:
public class Person {
private final PersonKey key;
private final String job;
public Person(long id, String name, int age, String job) {
this.key = new PersonKey(id, name, age);
this.job = job;
}
public PersonKey getKey() { return key; }
public String getJob() { return job; }
@Override
public String toString() {
return String.format("%d %s %d %s", key.id(), key.name(), key.age(), job);
}
}
使用 Stream 分组并聚合 job 字段:
List<person> persons = List.of(
new Person(1, "Jane", 25, "job1"),
new Person(1, "Jane", 25, "job2"),
new Person(1, "Jane", 25, "job3"),
new Person(2, "Adam", 30, "job4"),
new Person(2, "Adam", 30, "job5")
);
// 按 PersonKey 分组,提取 job 构成 List<string>
Map<personkey list>> grouped = persons.stream()
.collect(Collectors.groupingBy(
Person::getKey,
Collectors.mapping(Person::getJob, Collectors.toList())
));
// 输出格式化结果
grouped.forEach((key, jobs) ->
System.out.printf("%d %s %d %s%n", key.id(), key.name(), key.age(), jobs)
);</personkey></string></person>
输出:
1 Jane 25 [job1, job2, job3] 2 Adam 30 [job4, job5]
⚠️ 注意事项与最佳实践
- 键的完整性:PersonKey 必须包含所有用于判等的字段(id、name、age),缺一不可;否则分组逻辑将失效。
- null 安全:若字段可能为 null,record 的默认 equals/hashCode 仍能正确处理(Java 14+ record 对 null 友好)。
- 性能考量:避免在 groupingBy 的 key mapper 中创建新对象(如 new PersonKey(...))——应复用已有字段或预构建键。
- 替代方案(不推荐):拼接字符串作为 key(如 id + "_" + name + "_" + age)易出错、不可读、无法类型安全校验,应避免。
✅ 总结
按多属性分组的本质是定义语义正确的分组键。借助 record 类声明不可变复合键,配合 Collectors.groupingBy + Collectors.mapping,即可在一行流式调用中完成高效、可读、可维护的分组聚合。这是 Java 8+ 处理此类需求的标准范式。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











