Java 8、合并两个或多个嵌套列表
Java 8 , Merge two or more nested list
我需要合并 inner/nested 数组:
Pojo 结构
要求:如果有 2 个列表或 X 个列表要合并,我如何在 java 8 中实现?合并嵌套数组的最简单方法是什么?
private class Student {
private int studentId;
private List<Marks> markList = new ArrayList<>();
}
private class Marks {
private Integer subjectId;
private String subjectName;
private Integer mark;
}
需要合并以下 2 条记录:
{
"studentId": 1,
"Marks": [
{
"subjectId": 1,
"mark": 10
},
{
"subjectId": 2,
"mark": 10
}
]
}
{
"studentId": 1,
"Marks": [
{
"subjectId": 1,
"mark": 15
},
{
"subjectId": 3,
"mark": 10
}
]
}
给出最终预期结果为:
{
"studentId": 1,
"Marks": [
{
"subjectId": 1,
"mark": 25 //Addition of record 1 and 2
},
{
"subjectId": 2,
"mark": 10
}
{
"subjectId": 3,
"mark": 10
}
]
}
您可以使用终端操作 collect(Collectors.toMap())
通过 ID 映射每个学生,然后处理冲突情况以将不同的学生实例合并为一个新实例。
那时,当实例化一个新的 Student
时,您可以实现一个嵌套流来合并两个冲突实例的标记。通过应用第二个 collect(Collectors.toMap())
,您可以按主题 ID 对标记进行分组,然后通过合并标记的值再次处理冲突案例。
在下面的代码片段中,我通过添加第二个 Student
:
丰富了您的测试用例
List<Student> list = new ArrayList<>(List.of(
new Student(1, new ArrayList<>(List.of(new Marks(1, 10), new Marks(2, 10)))),
new Student(1, new ArrayList<>(List.of(new Marks(1, 15), new Marks(3, 10)))),
new Student(2, new ArrayList<>(List.of(new Marks(1, 5), new Marks(2, 10)))),
new Student(2, new ArrayList<>(List.of(new Marks(2, 5), new Marks(3, 10))))
));
//Temporary map
Map<Integer, Student> mapTemp = list.stream()
.collect(Collectors.toMap(Student::getStudentId, //grouping by student id
Function.identity(), //setting as value the student
(s1, s2) -> new Student(s1.getStudentId(), new ArrayList<>( //Creating a new Student whose list of marks is given by the merged marks of the two colliding students
Stream.concat(s1.getMarkList().stream(), s2.getMarkList().stream()) //Chaining the two lists of marks into a single stream
.collect(Collectors.toMap(Marks::getSubjectId, //Grouping by the marks by the subject id
Function.identity(), //Setting as value the mark
(m1, m2) -> new Marks(m1.getSubjectId(), m1.getMark() + m2.getMark()))) //Handling the colliding marks by summing them together
.values()))) //Retrieving the collection of merged marks
);
//Result list with the merged students
List listRes = new ArrayList(mapTemp.values());
System.out.println(listRes);
这里还有一个link来测试上面的代码:
由于您使用的是嵌套列表,因此解决问题的最佳方法是使用 MAP
。
List<Student> studentList = new ArrayList<>();
studentList.add(new Student(1,new ArrayList<Marks>(){{
add(new Marks(1,10));
add(new Marks(2,8));
}}));
studentList.add(new Student(1,new ArrayList<Marks>(){{
add(new Marks(1,5));
add(new Marks(2,8));
add(new Marks(3,6));
}}));
您可以添加更多学生和他们的分数以进行更多测试。
主要的 objective 是为每个学生计算每个科目的分数并将其存储到 Map
对象中。
//Storing the latest merged marks for each students .
Map<Integer,List<Marks>> listMap = new HashMap<Integer,List<Marks>>();
for(Student student: studentList){
if(!listMap.containsKey(student.getStudentId())){
listMap.put(student.getStudentId(),student.getMarkList());
}else{
/** storing individual marks of each subject for this student
* <k,v> = <SubjectID ,Marks>
*/
Map<Integer,Integer> merge = new HashMap<>();
// storing existing marks of any subjectID.
for(Marks oldMark : listMap.get(student.getStudentId())){
merge.put(oldMark.getSubjectId(),oldMark.getMark());
}
// calculating new marks as per each subject id
for(Marks newMark : student.getMarkList()){
// checking whether subject has any old values or not .
int val = merge.get(newMark.getSubjectId()) == null ? 0: merge.get(newMark.getSubjectId()) ;
merge.put(newMark.getSubjectId(),val+newMark.getMark());
}
//creating new merged marks list
List<Marks> temp = new ArrayList<Marks>();
for(int sid : merge.keySet()){
temp.add(new Marks(sid,merge.get(sid)));
}
// updating the main map with new merged values
listMap.put(student.getStudentId(),temp);
}
}
获得最终合并地图后,如果需要,您可以将其转换为学生类型的列表。
我需要合并 inner/nested 数组:
Pojo 结构
要求:如果有 2 个列表或 X 个列表要合并,我如何在 java 8 中实现?合并嵌套数组的最简单方法是什么?
private class Student {
private int studentId;
private List<Marks> markList = new ArrayList<>();
}
private class Marks {
private Integer subjectId;
private String subjectName;
private Integer mark;
}
需要合并以下 2 条记录:
{
"studentId": 1,
"Marks": [
{
"subjectId": 1,
"mark": 10
},
{
"subjectId": 2,
"mark": 10
}
]
}
{
"studentId": 1,
"Marks": [
{
"subjectId": 1,
"mark": 15
},
{
"subjectId": 3,
"mark": 10
}
]
}
给出最终预期结果为:
{
"studentId": 1,
"Marks": [
{
"subjectId": 1,
"mark": 25 //Addition of record 1 and 2
},
{
"subjectId": 2,
"mark": 10
}
{
"subjectId": 3,
"mark": 10
}
]
}
您可以使用终端操作 collect(Collectors.toMap())
通过 ID 映射每个学生,然后处理冲突情况以将不同的学生实例合并为一个新实例。
那时,当实例化一个新的 Student
时,您可以实现一个嵌套流来合并两个冲突实例的标记。通过应用第二个 collect(Collectors.toMap())
,您可以按主题 ID 对标记进行分组,然后通过合并标记的值再次处理冲突案例。
在下面的代码片段中,我通过添加第二个 Student
:
List<Student> list = new ArrayList<>(List.of(
new Student(1, new ArrayList<>(List.of(new Marks(1, 10), new Marks(2, 10)))),
new Student(1, new ArrayList<>(List.of(new Marks(1, 15), new Marks(3, 10)))),
new Student(2, new ArrayList<>(List.of(new Marks(1, 5), new Marks(2, 10)))),
new Student(2, new ArrayList<>(List.of(new Marks(2, 5), new Marks(3, 10))))
));
//Temporary map
Map<Integer, Student> mapTemp = list.stream()
.collect(Collectors.toMap(Student::getStudentId, //grouping by student id
Function.identity(), //setting as value the student
(s1, s2) -> new Student(s1.getStudentId(), new ArrayList<>( //Creating a new Student whose list of marks is given by the merged marks of the two colliding students
Stream.concat(s1.getMarkList().stream(), s2.getMarkList().stream()) //Chaining the two lists of marks into a single stream
.collect(Collectors.toMap(Marks::getSubjectId, //Grouping by the marks by the subject id
Function.identity(), //Setting as value the mark
(m1, m2) -> new Marks(m1.getSubjectId(), m1.getMark() + m2.getMark()))) //Handling the colliding marks by summing them together
.values()))) //Retrieving the collection of merged marks
);
//Result list with the merged students
List listRes = new ArrayList(mapTemp.values());
System.out.println(listRes);
这里还有一个link来测试上面的代码:
由于您使用的是嵌套列表,因此解决问题的最佳方法是使用 MAP
。
List<Student> studentList = new ArrayList<>();
studentList.add(new Student(1,new ArrayList<Marks>(){{
add(new Marks(1,10));
add(new Marks(2,8));
}}));
studentList.add(new Student(1,new ArrayList<Marks>(){{
add(new Marks(1,5));
add(new Marks(2,8));
add(new Marks(3,6));
}}));
您可以添加更多学生和他们的分数以进行更多测试。
主要的 objective 是为每个学生计算每个科目的分数并将其存储到 Map
对象中。
//Storing the latest merged marks for each students .
Map<Integer,List<Marks>> listMap = new HashMap<Integer,List<Marks>>();
for(Student student: studentList){
if(!listMap.containsKey(student.getStudentId())){
listMap.put(student.getStudentId(),student.getMarkList());
}else{
/** storing individual marks of each subject for this student
* <k,v> = <SubjectID ,Marks>
*/
Map<Integer,Integer> merge = new HashMap<>();
// storing existing marks of any subjectID.
for(Marks oldMark : listMap.get(student.getStudentId())){
merge.put(oldMark.getSubjectId(),oldMark.getMark());
}
// calculating new marks as per each subject id
for(Marks newMark : student.getMarkList()){
// checking whether subject has any old values or not .
int val = merge.get(newMark.getSubjectId()) == null ? 0: merge.get(newMark.getSubjectId()) ;
merge.put(newMark.getSubjectId(),val+newMark.getMark());
}
//creating new merged marks list
List<Marks> temp = new ArrayList<Marks>();
for(int sid : merge.keySet()){
temp.add(new Marks(sid,merge.get(sid)));
}
// updating the main map with new merged values
listMap.put(student.getStudentId(),temp);
}
}
获得最终合并地图后,如果需要,您可以将其转换为学生类型的列表。