假設你的學生招收到課程集團通過將Java 8
Class Student{
ArrayList<Course> courses;
}
Class Course{
String id;
String name;
}
如何使用GROUPBY功能與Java 8到參加特定課程
假設你的學生招收到課程集團通過將Java 8
Class Student{
ArrayList<Course> courses;
}
Class Course{
String id;
String name;
}
如何使用GROUPBY功能與Java 8到參加特定課程
學生的列表,你要同學生進行分類不同的組,groupingBy
收集器在這裏不適合(它將每個流元素精確地放到一個組中)。
這將是更有效的通過forEach
創建一個可變的容器(如HashMap
)和填充它:
Map<Course, List<Student>> result = new HashMap<>();
students.forEach(student -> student.courses.forEach(
course -> result.computeIfAbsent(course, c -> new ArrayList<>()).add(student)));
如果你想使用groupingBy
您可以將不是學生,但學生當然對,儘管您需要執行下游收集步驟:
import static java.util.stream.Collectors.*;
Map<Course, List<Student>> result = students.stream()
.<Map.Entry<Course, Student>>flatMap(
student -> student.courses.stream()
.map(course -> new AbstractMap.SimpleEntry<>(course, student)))
.collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())));
看起來有點醜陋。我StreamEx庫增加了一些快捷方式,這樣的場景:
Map<Course, List<Student>> result = StreamEx.of(students)
.cross(s -> s.courses.stream()).invert().grouping();
這看起來好多了,但普通的解決方案看起來還是更好的是(並且不需要第三方庫)。
我不得不承認,我使用@ tagir-valeev回答的想法。
創建一個簡單的類
public class CourseStundentPair {
private Course course;
private Student student;
public CourseStundentPair(Course course, Student student) {
this.course = course;
this.student = student;
}
...
}
這將使得代碼更conice和可讀性。
只是出於說服我加名外地學生
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
注意,在Eclipse IDE中可能會抱怨編譯錯誤,在它的IntelliJ會正常工作。
謝謝Tagir Valeev.That很有用 –
顯式類型'>'不應該是必需的。 –
Holger