【问题标题】:Get summary for multiple class fields in Java8 using map reduce technique使用 map reduce 技术获取 Java8 中多个类字段的摘要
【发布时间】:2016-04-18 10:52:27
【问题描述】:

以下是学生类定义:

class Student{
    String name;
    int sub1;
    int sub2;
    int sub3;

    // etc...etc...
}

我有所有学生的名单。 要求是求 sub1、sub2 和 sub3 的平均值。并且还可以为任何学生获得任何科目的最低分数和最高分数。

下面是sub1的代码:

    IntSummaryStatistics sub1Summary = students.stream().collect(Collectors.summarizingInt(s -> s.sub1));

是否可以使用单个表达式,或者我必须为每个主题创建IntSummaryStatistics并比较每个最低和最高主题值?

提前致谢

【问题讨论】:

  • 你所说的任何科目的最低分和最高分是什么意思?您是否想要结果 3 IntSummaryStatistics、一个总结 sub1、一个用于 sub2 和一个用于 sub3?还是subs 之间的最小相关?
  • 有学生名单。我想在任何学生的任何科目(sub1、sub2 或 sub3)中获得学生的最低分数和学生的最高分数。所以我将只有一个最低和最高的价值整个列表
  • 科目一的平均分,科目二的平均分,科目三的平均分
  • 没有单行,抱歉。如果您想要阅读检查this threadthat oneyet another thread...
  • 您需要编写自己的收集器来汇总您所有的subs,或者为每个sub 创建一个IntSummaryStatistics

标签: mapreduce java-8


【解决方案1】:

尝试以下:

  List<Student> students = Arrays.asList(Student.create("A", 60, 55, 35), 
                    Student.create("B", 40, 65, 75),
                    Student.create("C", 70, 45, 95));

        Map<String, IntSummaryStatistics> subjectsSummary = new HashMap<String, IntSummaryStatistics>();
        Map<String, List<Integer>> subjectMarks = new HashMap<String, List<Integer>>();

        List<Integer> sub1Marks = new ArrayList<>();
        List<Integer> sub2Marks = new ArrayList<>();
        List<Integer> sub3Marks = new ArrayList<>();

    // Input : Student
    // Output : Map(Key=SubjectName, Value= List of Marks for students)
    Function<Student, Map<String, List<Integer>>> toSubjectsMap = (s) -> {
        sub1Marks.add(s.getSub1());
        sub2Marks.add(s.getSub2());
        sub3Marks.add(s.getSub3());

        subjectMarks.put("Sub1", sub1Marks);
        subjectMarks.put("Sub2", sub2Marks);
        subjectMarks.put("Sub3", sub3Marks);

        return subjectMarks;
    };

    //Function to generate summary stats from the list of integers/marks
        Function<List<Integer>, IntSummaryStatistics> generateStatsFunc = (listOfMarks) -> {
            return listOfMarks.stream().collect(Collectors.summarizingInt(marks->marks));
        };


    // 1. Students are mapped to generate Map for subject-->List of Marks
    // 2. Doing flatMap on the generate Map to get the Keys from the map(list of subjects)
    // 3. Collecting the Keys(Subject Names) of Map to Map(Key=SubjectName,Value=IntSummaryStats for Subject)
    students.stream().map(toSubjectsMap).flatMap(subMap -> subMap.keySet().stream())
            .collect(() -> subjectsSummary/* Initial Value of Map */, (summary, key) -> {
                // Generate the stats from the list of marks for the subject 
                IntSummaryStatistics st = generateStatsFunc.apply(subjectMarks.get(key));
                //Adding the stats for each Subject into the result Summary
                summary.put(key, st);
            } , (summary1, summary2) -> {
                //merging the two maps
                summary1.putAll(summary2);
            });

    System.out.println(subjectsSummary);

和Student类如下:

class Student {
    String name;
    int sub1;
    int sub2;
    int sub3;

    static Student create(String name, int sub1, int sub2, int sub3) {
        // validation
        return new Student(name, sub1, sub2, sub3);
    }

    public String getName() {
        return name;
    }

    public int getSub1() {
        return sub1;
    }

    public int getSub2() {
        return sub2;
    }

    public int getSub3() {
        return sub3;
    }

    private Student(String name, int sub1, int sub2, int sub3) {
        this.name = name;
        this.sub1 = sub1;
        this.sub2 = sub2;
        this.sub3 = sub3;
    }

    @Override
    public String toString() {
        return name;
    }
}

【讨论】:

  • 太棒了.. 看起来我必须花 5-6 个小时来理解那个 stream() 块。如果可能,请添加 cmets。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-08
相关资源
最近更新 更多