java Map< String,Map< String,Double>> streamapi [duplicate]

fbcarpbf  于 2023-05-12  发布在  Java
关注(0)|答案(3)|浏览(125)

此问题已在此处有答案

Sort a Map<Key, Value> by values(64答案)
3天前关闭。
我不明白为什么我的代码不工作。告诉我,如果不难,我真的问。错误的流,但我不能弄清楚为什么我不能填补Map从列表我想知道什么是学生的整体GPA。结果应采用以下形式:密钥-组值-学生姓名-分数,学生姓名-分数

class Student4 {

    String name;
    Subject4[] subjects;

    public Student4(String name, Subject4[] subjects) {
        this.name = name;
        this.subjects = subjects;
    }

    public static void main(String[] args) {

        Student4 s1 = new Student4("Name1", new Subject4[]{
                new Subject4("A", new Integer[]{4, 4, 4, 4, 5}), //21 -> 4.2
                new Subject4("B", new Integer[]{5, 5, 5, 5, 5}), //25 -> 5.0
                new Subject4("C", new Integer[]{4, 4, 4, 4, 5})  //21 -> 4.2
        });
        Student4 s2 = new Student4("Name2", new Subject4[]{
                new Subject4("A", new Integer[]{3, 3, 3, 4, 5}), //18 -> 3.6
                new Subject4("B", new Integer[]{5, 3, 3, 5, 5}), //21 -> 4.2
                new Subject4("C", new Integer[]{4, 3, 3, 4, 3})  //17 -> 3.4
        });
        Student4 s3 = new Student4("Name3", new Subject4[]{
                new Subject4("A", new Integer[]{5, 5, 5, 4, 5}), //24 -> 4.8
                new Subject4("B", new Integer[]{5, 5, 5, 4, 5}), //24 -> 4.8
                new Subject4("C", new Integer[]{5, 5, 5, 4, 5})  //24 -> 4.8
        });
        Student4 s4 = new Student4("Name4", new Subject4[]{
                new Subject4("A", new Integer[]{5, 5, 5, 4, 5}), //24 -> 4.8
                new Subject4("B", new Integer[]{5, 5, 5, 4, 5}), //24 -> 4.8
                new Subject4("C", new Integer[]{5, 5, 5, 4, 5})  //24 -> 4.8
        });

        Map<String, List<Student4>> group = new HashMap<>();
        group.put("group1", List.of(s1, s2));
        group.put("group2", List.of(s3, s4));


        Map<String, Map<String, Double>> averageByStudent = group.entrySet().stream()
                .collect(Collectors.toMap(entry -> entry.getKey(),
                        entry -> entry.getValue().stream()
                                .collect(Collectors.toMap(entry.getValue().stream()
                                                .map(z -> z.name),
                                        entry.getValue().stream()
                                                .flatMap(v -> Arrays.stream(v.subjects))
                                                .flatMap(w -> Arrays.stream(w.mark))
                                                .mapToDouble(Integer::doubleValue)
                                                .average().getAsDouble()
                                ))));
    }
}

class Subject4 {

    String name;
    Integer[] mark;

    public Subject4(String name, Integer[] mark) {
        this.name = name;
        this.mark = mark;
    }
}
oknwwptz

oknwwptz1#

我认为问题是在使用Collectors.toMap时,这个函数需要两个函数作为参数;一个生成键,另一个生成值(它不期望值流)
这个应该能用

import static java.util.stream.Collectors.toMap;

Map<String, Map<String, Double>> averageByStudent = group.entrySet().stream()
        .collect(toMap(Entry::getKey,
            entry -> entry.getValue().stream()
                .collect(toMap(student -> student.name, student ->
                    Arrays.stream(student.subjects)
                        .flatMap(w -> Arrays.stream(w.mark))
                        .mapToDouble(Integer::doubleValue)
                        .average().orElse(0d)
                ))));
wr98u20j

wr98u20j2#

为了弄清楚这一点,我将遵循以下方法:
在lambda中为变量名使用一个合适的上下文相对名称,这样你就可以知道entry在第一次和第二次collect调用中有不同的含义(我将它们重命名为entryKeyStringValueListOfStudentsstudent,以了解每种情况下的含义)。
通过重命名,您可能会发现行

Collectors.toMap(entry.getValue().stream()
.map(z -> z.name),

是没有意义的,因为您当前的“流”对象是一个Student,所以不需要Map。
然后修改这两个,你会得到更简单的代码:student -> student.studentName,用于呈现键,student -> Arrays.stream(student.subjects)用于Map主题(这里不需要flatMap,您只需流式传输主题并Map标记)。
经过这些更改(以及一些用于澄清的缩进,虽然不是最漂亮的),您最终会得到:

Map<String, Map<String, Double>> averageByStudent = group.entrySet().stream()
        .collect(Collectors.toMap(
                entryKeyStringValueListOfStudents -> entryKeyStringValueListOfStudents.getKey(),
                entryKeyStringValueListOfStudents -> entryKeyStringValueListOfStudents.getValue()
                        .stream() //stream of students
                        .collect(Collectors.toMap(
                                    student -> student.studentName,
                                    student -> Arrays.stream(student.subjects) //stream of subjects
                                        .flatMap(subject -> Arrays.stream(subject.mark)) //stream of marks
                                        .mapToDouble(Integer::doubleValue)
                                        .average()
                                        .getAsDouble()
                                                 )
                                )
                        )
                );
643ylb08

643ylb083#

更正:

Map<String, Map<String, Double>> averageByStudent = group.entrySet().stream()
        .collect(Collectors.toMap(grp -> grp.getKey(), // group1
                grp -> grp.getValue().stream() // s1, s2 etc..
                        .collect(Collectors.toMap(student -> student.name,
                                student -> Arrays.stream(student.subjects)
                                .flatMap(subject -> Arrays.stream(subject.mark))
                                .mapToDouble(Double::valueOf).average().getAsDouble()))
        ));

相关问题