使用流使用来自另一个列表的值填充地图的值

时间:2019-11-26 06:26:24

标签: java java-8 java-stream

鉴于我有一个Map<String, List<Student>>类型的映射和一个List<Student>类型的列表。如何使用流使用List<Student>中的元素填充地图的列表值(最初是空列表)?

“字符串”键应该是一门课程(例如数学或英语),并且每个学生都有一个包含其所有课程的集合。我想将每门课程用作地图中的键,其值是所有参加该课程的学生的列表。

这是我的代码:

studentMap.entrySet().stream()
.map(entry -> entry.getValue()).
collect(studentList.stream().map(student -> student.getClasses() //Returns a set of that student's courses));

我的代码不起作用,因为我不知道如何从地图的课程键中获取一组学生的课程。

3 个答案:

答案 0 :(得分:1)

如果您的要求是仅添加到现有的Map而不创建新的KVS,则可以尝试如下操作:

Map<String, List<Student>> map = new HashMap<>();
students.stream()
            .flatMap(student -> student.getClasses().stream().map(classname -> new AbstractMap.SimpleEntry<>(classname, student)))
            .forEach(entry -> map.get(entry.getKey()).add(entry.getValue())); // use it if you are completly sure that there is a key for this class in your map

但是,它混合了“流”和“迭代”方法,并修改了流之外的Map,这使其产生副作用。

如果您想直接将List转换为新的Map,则可以使用:

Map<String, List<Student>> myMap = students.stream()
            .flatMap(student -> student.getClasses().stream().map(classname -> new AbstractMap.SimpleEntry<>(classname, student)))
            .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())));

然后,如果您确定目标地图具有所有键,则可以使用它来合并:

for(Map.Entry<String, List<Student>> entry : myMap.entrySet()) {
    map.get(entry.getKey()).addAll(entry.getValue());
}

答案 1 :(得分:0)

我用嵌套流弄清楚了:

studentList.stream().forEach(
   student-> {
       student.getCourses().stream().
       forEach(courseName -> {
       List<Student> students = studentMap.get(courseName);
       students.add(student);
       studentMap.put(courseName, students);
       });
     }
   );

答案 2 :(得分:-1)

我对Java 8上的流和收集函数还不是很熟悉,但是如果您在List上启动流,那么它比StudentMap好吗?我在下面使用并行流和forEach函数编写了代码。让我知道这是否是您想要的。如果您更高级地使用Java 8来满足您的要求,请告诉我。我也想提高对Java 8的了解。

List<Student> students = new ArrayList<Student>();

students.add(new Student("a", "Math"));
students.add(new Student("b", "Math"));
students.add(new Student("c", "Science"));
students.add(new Student("d", "Science"));

Map<String, List<Student>> map = new HashMap<String, List<Student>>();

students.parallelStream().forEach(student ->{

    String course = student.course;
        if(map.get(course) != null) {
            map.get(course).add(student);
        }else {
            List<Student> filteredStudent = new ArrayList<Student>();
            filteredStudent.add(student);
            map.put(course, filteredStudent);
        }

    });