fas*_*ava 5 java collections java-stream
我有学生名单.我想返回具有课程的对象列表StudentResponse课程以及课程的学生列表.所以我可以写一下给我一张地图
Map<String, List<Student>> studentsMap = students.stream().
.collect(Collectors.groupingBy(Student::getCourse,
Collectors.mapping(s -> s, Collectors.toList()
)));
Run Code Online (Sandbox Code Playgroud)
现在我必须再次遍历地图以创建StudentResponse具有课程和列表的类对象 列表:
class StudentResponse {
String course;
Student student;
// getter and setter
}
Run Code Online (Sandbox Code Playgroud)
有没有办法结合这两个迭代?
不完全是您所要求的,但为了完整起见,这是一种完成您想要的事情的紧凑方法:
Map<String, StudentResponse> map = new LinkedHashMap<>();
students.forEach(s -> map.computeIfAbsent(
s.getCourse(),
k -> new StudentResponse(s.getCourse()))
.getStudents().add(s));
Run Code Online (Sandbox Code Playgroud)
这假设StudentResponse有一个构造函数,它接受课程作为参数和学生列表的 getter,并且该列表是可变的(即ArrayList),以便我们可以将当前学生添加到其中。
虽然上述方法有效,但它显然违反了面向对象的基本原则,即封装。如果您对此表示同意,那么您就完成了。如果您想遵循封装,那么您可以添加一个方法来StudentResponse添加Student实例:
public void addStudent(Student s) {
students.add(s);
}
Run Code Online (Sandbox Code Playgroud)
那么,解决方案将变成:
Map<String, StudentResponse> map = new LinkedHashMap<>();
students.forEach(s -> map.computeIfAbsent(
s.getCourse(),
k -> new StudentResponse(s.getCourse()))
.addStudent(s));
Run Code Online (Sandbox Code Playgroud)
该解决方案显然比前一个解决方案更好,并且可以避免严重的代码审查者的拒绝。
两种解决方案都依赖于Map.computeIfAbsent,它要么返回StudentResponse所提供课程的 a (如果地图中存在该课程的条目),要么创建并返回StudentResponse使用该课程作为参数构建的实例。然后,该学生将被添加到返回的学生的内部列表中StudentResponse。
最后,您的StudentResponse实例位于映射值中:
Collection<StudentResponse> result = map.values();
Run Code Online (Sandbox Code Playgroud)
如果您需要 aList而不是 a Collection:
List<StudentResponse> result = new ArrayList<>(map.values());
Run Code Online (Sandbox Code Playgroud)
注意:我使用LinkedHashMap而不是HashMap保留插入顺序,即原始列表中学生的顺序。如果没有这样的需求,直接使用即可HashMap。
| 归档时间: |
|
| 查看次数: |
188 次 |
| 最近记录: |