我有学生名单。
我想返回具有该类(class)的对象StudentResponse类的列表以及该类(class)的学生列表。
所以我可以写给我一张 map
Map<String, List<Student>> studentsMap = students.stream().
.collect(Collectors.groupingBy(Student::getCourse,
Collectors.mapping(s -> s, Collectors.toList()
)));
现在,我必须再次遍历 map 以创建具有类(class)和列表的
StudentResponse
类的对象列表:class StudentResponse {
String course;
Student student;
// getter and setter
}
有没有办法结合这两个迭代?
最佳答案
并非完全符合您的要求,但这是一种紧凑的方法来完成您想要的内容,只是为了保持完整性:
Map<String, StudentResponse> map = new LinkedHashMap<>();
students.forEach(s -> map.computeIfAbsent(
s.getCourse(),
k -> new StudentResponse(s.getCourse()))
.getStudents().add(s));
假设
StudentResponse
具有构造函数,该构造函数将类(class)作为参数接受并且是学生列表的 getter ,并且该列表是可变的(即ArrayList
),以便我们可以向其添加当前学生。虽然上述方法有效,但显然违反了基本的OO原则,即封装。如果您对此表示满意,那么您就完成了。如果要遵守封装,则可以在
StudentResponse
中添加一个方法来添加Student
实例:public void addStudent(Student s) {
students.add(s);
}
然后,解决方案将变为:
Map<String, StudentResponse> map = new LinkedHashMap<>();
students.forEach(s -> map.computeIfAbsent(
s.getCourse(),
k -> new StudentResponse(s.getCourse()))
.addStudent(s));
这种解决方案显然比以前的解决方案更好,并且可以避免遭到认真的代码审查者的拒绝。
两种解决方案都依赖
Map.computeIfAbsent
,后者为提供的类(class)返回StudentResponse
(如果在 map 中存在该类(class)的条目),或者创建并返回以类(class)为参数构建的StudentResponse
实例。然后,将学生添加到返回的StudentResponse
的学生的内部列表中。最后,您的
StudentResponse
实例位于 map 值中:Collection<StudentResponse> result = map.values();
如果您需要
List
而不是Collection
:List<StudentResponse> result = new ArrayList<>(map.values());
注意:我使用的是
LinkedHashMap
而不是HashMap
来保留插入顺序,即学生在原始列表中的顺序。如果您没有这样的要求,请使用HashMap
。