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

时间:2018-04-30 07:56:41

标签: java-8 java-stream nested-loops

假设我有两节课。

课程类

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

学生班级

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()))));

2 个答案:

答案 0 :(得分:4)

这样的事情应该有效(SimpleEntry是一个实现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和Stream对的Student。获得Stream后,您可以使用groupingBy获取所需的输出Map

答案 1 :(得分:4)

 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())));