
本文介绍两种高效合并具有相同 id 的 person 对象的方法:使用 hashmap 手动聚合,或借助 stream api 配合 groupingby 实现函数式合并,最终生成去重且位置信息聚合的唯一对象列表。
本文介绍两种高效合并具有相同 id 的 person 对象的方法:使用 hashmap 手动聚合,或借助 stream api 配合 groupingby 实现函数式合并,最终生成去重且位置信息聚合的唯一对象列表。
在实际开发中,我们常需对 List
✅ 方案一:使用 HashMap 手动聚合(推荐用于复杂逻辑或需复用中间状态)
该方法时间复杂度为 O(n),清晰可控,适合需要自定义合并策略(如 contract 值取最大/平均/首个)的场景:
Map<Integer, Person> mergedMap = new HashMap<>();
for (Person person : list) {
int id = person.getId();
if (!mergedMap.containsKey(id)) {
// 首次遇到该 ID,深拷贝或新建 Person(避免引用污染)
mergedMap.put(id, new Person(
person.getId(),
person.getContract(), // 此处可改为 Math.max(existing.getContract(), person.getContract())
new ArrayList<>(person.getPositions())
));
} else {
Person existing = mergedMap.get(id);
existing.getPositions().addAll(person.getPositions());
// 注意:若 contract 需要合并(如求和),此处补充逻辑
}
}
List<Person> mergedList = new ArrayList<>(mergedMap.values());⚠️ 注意事项:
- 原始 Person 类中的 position 字段应为 List
(首字母大写更符合 Java 命名规范,建议修正类名 position → Position); - 若 Person 包含可变状态(如 contract),需明确业务规则(保留首个?取最大值?累加?),示例中默认保留第一个出现的 contract 值;
- 使用 new ArrayList(...) 避免后续操作影响原始对象。
✅ 方案二:使用 Stream + Collectors.groupingBy()(函数式、简洁)
适用于逻辑简单、强调代码可读性与不可变性的场景:
立即学习“Java免费学习笔记(深入)”;
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
List<Person> mergedList = list.stream()
.collect(Collectors.groupingBy(
Person::getId,
LinkedHashMap::new, // 保持插入顺序(可选)
Collectors.collectingAndThen(
Collectors.toList(),
group -> {
Person first = group.get(0);
List<Position> allPositions = group.stream()
.flatMap(p -> p.getPositions().stream())
.collect(Collectors.toList());
return new Person(
first.getId(),
first.getContract(), // 同样可替换为 group.stream().mapToInt(Person::getContract).sum()
allPositions
);
}
)
))
.values()
.stream()
.collect(Collectors.toList());? 提示:groupingBy 返回 Map
>,配合 collectingAndThen 可在分组后立即对每个 List 执行自定义聚合逻辑,避免额外遍历。
✅ 最终效果
无论采用哪种方案,输入:
Person p1 = new Person(1, 470, List.of(new Position(45, LocalDate.now()), new Position(42, LocalDate.now()))); Person p2 = new Person(1, 320, List.of(new Position(35, LocalDate.now()))); List<Person> list = List.of(p1, p2);
都将输出唯一一个 Person 对象:
Person{id=1, contract=470, positions=[Position{id=45,...}, Position{id=42,...}, Position{id=35,...}]}✅ 总结:优先选用 方案一(HashMap) 以保障性能与可维护性;若项目已重度使用 Stream 且逻辑简单,方案二更具表达力。两者均避免了原始代码中“边遍历边修改”及“未去重”的根本缺陷。

















