Java中如何按相同属性值合并两个存储对象的ArrayList
问题描述
现有两个ArrayList:
- 第一个存储学生基础信息,每个对象包含
id、name、city三个属性 - 第二个存储学生成绩信息,每个对象包含
id、marks、grade三个属性
需要以两个列表共有的id字段为匹配依据,将对应的对象合并为同时包含学生基础信息和成绩信息的新对象,最终得到合并后的列表。
示例数据
// 学生基础信息 [ { "id": 1, "name": "sam", "city": "Chennai" }, { "id": 2, "name": "peter", "city": "Chennai" } ]
// 学生成绩信息 [ { "id": 1, "marks": 95, "grade": "A" }, { "id": 2, "marks":63, "grade": "B" } ]
// 期望输出 [ { "id": 1, "name": "sam", "city": "Chennai", "marks": 95, "grade": "A" }, { "id": 2, "name": "peter", "city": "Chennai", "marks":63, "grade": "B" } ]
原JS实现代码:
async mergeData(data1, data2, key) { const result = data1.map(a => Object.assign({}, a, data2.find(b => b[key] === a[key]) ) ) return result }
Java实现方案
1. 定义对应实体类
使用Lombok的@Data注解简化getter、setter代码,无Lombok的场景手动补充对应方法即可。
// 学生基础信息实体 import lombok.Data; @Data public class StudentDetail { private Integer id; private String name; private String city; }
// 学生成绩信息实体 import lombok.Data; @Data public class StudentGrade { private Integer id; private Integer marks; private String grade; }
// 合并后的学生信息实体 import lombok.Data; @Data public class StudentVO { private Integer id; private String name; private String city; private Integer marks; private String grade; public StudentVO(StudentDetail detail, StudentGrade grade) { this.id = detail.getId(); this.name = detail.getName(); this.city = detail.getCity(); if (grade != null) { this.marks = grade.getMarks(); this.grade = grade.getGrade(); } } }
2. 合并逻辑实现
优先将成绩列表转为ID为key的Map,将时间复杂度控制在O(n+m),避免双重循环,性能远高于JS中原find的遍历匹配逻辑,更适合大数据量场景。
import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class StudentMergeService { public List<StudentVO> merge(List<StudentDetail> detailList, List<StudentGrade> gradeList) { // 构建ID和成绩的映射关系 Map<Integer, StudentGrade> gradeIdMap = gradeList.stream() .collect(Collectors.toMap(StudentGrade::getId, item -> item)); // 遍历基础信息列表匹配成绩,生成合并后的对象 return detailList.stream() .map(detail -> new StudentVO(detail, gradeIdMap.get(detail.getId()))) // 若需要过滤无成绩的学生,放开下面这行注释 // .filter(vo -> vo.getMarks() != null) .collect(Collectors.toList()); } }
内容的提问来源于stack exchange,提问作者monica_s
相关产品推荐
相关产品推荐

