流 - 嵌套集合 - 转换为地图

Stream - Nested Collection - Convert to Map

假设我有 2 个 类。

课程Class

public class Course {
    private int id;
    private String name;
}

学生Class

public class Student {
    private int id;
    private String name;
    private List<Course> courses;
}

我有 List<Student> 并且每个 Student 都注册了多个课程。

我需要使用 Java 8 流 API 过滤结果,如下所示。

Map<courseId, List<Student>> 

我试过以下,但没有成功:

第一种方法

Map<Integer, List<Student>> courseStudentMap = studentList.stream()
    .collect(Collectors.groupingBy(
        student -> student.getCourses().stream()
            .collect(Collectors.groupingBy(Course::getId))));

第二种方法

Map<Integer, List<Student>> courseStudentMap = studentList.stream()
    .filter(student -> student.getCourses().stream()
        .collect(Collectors.groupingBy(
            Course::getId, Collectors.mapping(Student::student, Collectors.toList()))));

这样的事情应该可行(其中 SimpleEntry 是一个 class 实现 Map.Entry<Integer,Student>:

Map<Integer, List<Student>> courseStudentMap =
    studentList.stream()
               .flatMap(s -> s.getCourses()
                              .stream()
                              .map(c -> new SimpleEntry<>(c.getId(),s)))
               .collect(Collectors.groupingBy(Map.Entry::getKey,
                        Collectors.mapping(Map.Entry::getValue,
                                           Collectors.toList())));

想法是首先将 Stream<Student> 转换为所有课程 ID 和 Student 对的 Stream。得到 Stream 后,您可以使用 groupingBy 获得所需的输出 Map.

 Map<Integer, List<Student>> result = studentsList
            .stream()
            .flatMap(x -> x.getCourses().stream().map(y -> new SimpleEntry<>(x, y.getId())))
            .collect(Collectors.groupingBy(
                    Entry::getValue,
                    Collectors.mapping(Entry::getKey, Collectors.toList())));