我有两个包含学生对象的列表。我想将 objects.status
属性聚合到两个 studentId 相似的列表中。
承诺List A中的status属性总是null
,List B中的status属性不是null
。
Student List A:
id:123, name: noname, status: null, address: xxxx, contact: xxx, ....
id:124, name: noname, status: null, address: xxxx, contact: xxx, ....
id:125, name: noname, status: null, address: xxxx, contact: xxx, ....
Student List B:
id:123, name: null, status: accepted, address: null, contact: null, ....
id:124, name: null, status: not-accepted, address: null, contact: null, ....
id:125, name: null, status: accepted, address: null, contact: null, ....
Aggregated list:
id:123, name: noname, status: accepeted, address: xxxx, contact: xxx, ....
id:124, name: noname, status: not-accepted, address: xxxx, contact: xxx, ....
id:125, name: noname, status: accepted, address: xxxx, contact: xxx, ....
通常,我会使用两个 for 循环来聚合两个结果。有没有更好的方法来做到这一点?
答案 0 :(得分:1)
对于流,您可以使用 groupingBy
的组合对相似的 id 进行分组,并通过选择具有非空状态的元素来减少分组的元素:
Stream.concat(a.stream(),b.stream())
.collect(Collectors.groupingBy(Student::getId,
Collectors.reducing((x,y) -> (x.getStatus() != null) ? x: y)))
.values()
.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList()); // returns a list of student objects.
我不确定这是否比传统的 for
循环“更好”,但这是一种方法。
答案 1 :(得分:0)
您可以将一个列表放入集合中。
并更新第二个/聚合列表,如下所示。
Map<Long, Student> uniqueStudents = new HashMap<>();
for(Student st : listA)
uniqueStudents.put(st.getId(), st);
for(int i = 0; i < listB.size(); i++)
{
Student studentB = listB.get(i);
Student studentA = uniqueStudents.get(studentB.getId());
// do aggregation.
}
答案 2 :(得分:0)
/*
approach : step 1> make a hash map of id->student from list A
step 2> traverse list B, find out the match from map and
make a combined record from list and map of same id,
and put that in the output list.
we can assume the existence of the Student class.
*/
List<Student> aggregate(List<Student> A, List<Student> B) {
Map<String, Student> hm = new HashMap<>();
for (Student student : A) {
hm.put(student.getId(), student);
}
List<Student> combined = new ArrayList<>();
for (Student student : B) {
if (hm.containsKey(student.getId())) {
Student s1 = new Student(student);//this copy constructor should present in
//the Student class
Student s2 = hm.get(student.getId());
//now combine both of them
// in this way we are combined all fields which is null in any list
if (s2.getName() != null) {
s1.setName(s2.getName());
}
if (s2.getStatus() != null) {
s1.setStatus(s2.getStatus());
}
if (s2.getAddress() != null) {
s1.setAddress(s2.getAddress());
}
if (s2.getContact() != null) {
s1.setContact(s2.getContact());
}
combined.add(s1);
}
}
return combined;
}