Lambda 按Java8分组
假设你是一名注册课程的学生Lambda 按Java8分组,lambda,group-by,java-8,Lambda,Group By,Java 8,假设你是一名注册课程的学生 Class Student{ ArrayList<Course> courses; } Class Course{ String id; String name; } 班级学生{ ArrayList课程; } 班级课程{ 字符串id; 字符串名; } 如何在java 8中使用groupBy函数列出参加特定课程的学生当您想将同一个学生划分为不同的组时,groupingBy收集器不适用于此处(它将每个流元素精确地放在一个组中) 创建一个可变容器
Class Student{
ArrayList<Course> courses;
}
Class Course{
String id;
String name;
}
班级学生{
ArrayList课程;
}
班级课程{
字符串id;
字符串名;
}
如何在java 8中使用groupBy函数列出参加特定课程的学生当您想将同一个学生划分为不同的组时,
groupingBy
收集器不适用于此处(它将每个流元素精确地放在一个组中)
创建一个可变容器(如HashMap
)并通过forEach
填充它会更有效:
Map<Course, List<Student>> result = new HashMap<>();
students.forEach(student -> student.courses.forEach(
course -> result.computeIfAbsent(course, c -> new ArrayList<>()).add(student)));
看起来有点难看。“我的库”为此类场景添加了一些快捷方式:
Map<Course, List<Student>> result = StreamEx.of(students)
.cross(s -> s.courses.stream()).invert().grouping();
Map result=streamx.of(学生)
.cross(s->s.courses.stream()).invert().grouping();
这看起来好得多,但简单的解决方案看起来仍然更好(并且不需要第三方库)。我必须承认,我使用的是@tagir valeev answer的想法。
创建一个简单的类
public class CourseStundentPair {
private Course course;
private Student student;
public CourseStundentPair(Course course, Student student) {
this.course = course;
this.student = student;
}
...
}
这将使代码更加简洁易读。只是出于说服力,我给学生添加了名称字段
import static java.util.stream.Collectors.*;
public class TestCourse {
public static void main(String[] args) {
Student student1 = new Student("1", "Student1");
Student student2 = new Student("2", "Student2");
Student student3 = new Student("3", "Student3");
Student student4 = new Student("4", "Student4");
Course course1 = new Course("c1", "English");
Course course2 = new Course("c2", "Mathematics");
Course course3 = new Course("c3", "Literature");
student1.getCourses().add(course1);
student1.getCourses().add(course2);
student1.getCourses().add(course3);
student2.getCourses().add(course1);
student2.getCourses().add(course2);
student3.getCourses().add(course1);
List<Student> students = new ArrayList<>();
students.add(student1);
students.add(student2);
students.add(student3);
students.add(student4);
final Map<Course, List<Student>> courseToStudents = students.stream()
.flatMap(s -> s.getCourses().stream().map(c -> new CourseStundentPair(c,s)))
.collect(groupingBy(CourseStundentPair::getCourse,
mapping(CourseStundentPair::getStudent, toList())
)
);
for (Course course :courseToStudents.keySet()){
System.out.printf("Course %s , Students: %s \n"
,course.getName()
,courseToStudents.get(course).stream().map(Student::getName)
.collect(joining(", ")));
}
}
请注意,在eclipse中,IDE可能会抱怨编译错误,而在Intellij中,它可以正常工作。谢谢Tagir Valeev。这很有用。显式类型
应该是不必要的。
import static java.util.stream.Collectors.*;
public class TestCourse {
public static void main(String[] args) {
Student student1 = new Student("1", "Student1");
Student student2 = new Student("2", "Student2");
Student student3 = new Student("3", "Student3");
Student student4 = new Student("4", "Student4");
Course course1 = new Course("c1", "English");
Course course2 = new Course("c2", "Mathematics");
Course course3 = new Course("c3", "Literature");
student1.getCourses().add(course1);
student1.getCourses().add(course2);
student1.getCourses().add(course3);
student2.getCourses().add(course1);
student2.getCourses().add(course2);
student3.getCourses().add(course1);
List<Student> students = new ArrayList<>();
students.add(student1);
students.add(student2);
students.add(student3);
students.add(student4);
final Map<Course, List<Student>> courseToStudents = students.stream()
.flatMap(s -> s.getCourses().stream().map(c -> new CourseStundentPair(c,s)))
.collect(groupingBy(CourseStundentPair::getCourse,
mapping(CourseStundentPair::getStudent, toList())
)
);
for (Course course :courseToStudents.keySet()){
System.out.printf("Course %s , Students: %s \n"
,course.getName()
,courseToStudents.get(course).stream().map(Student::getName)
.collect(joining(", ")));
}
}
Course English , Students: Student1, Student2, Student3
Course Literature , Students: Student1
Course Mathematics , Students: Student1, Student2