如何在Java8中进行分组和归约

如何在Java8中进行分组和归约,java,arraylist,lambda,java-8,java-stream,Java,Arraylist,Lambda,Java 8,Java Stream,因为我有主题的列表 "Subjects":[ {"subject":"Math","grades":1}, {"subject":"Math","grades":2}, {"subject":"Math","grades":3}, {"subject":"Math","grades":3}, {"subject":"Lab","grades":10}, {"subject":"Lab","grades":12} ] 我想这样分组和减少结果 //Expected Result "Subjects

因为我有主题的
列表

"Subjects":[
{"subject":"Math","grades":1},
{"subject":"Math","grades":2},
{"subject":"Math","grades":3},
{"subject":"Math","grades":3},
{"subject":"Lab","grades":10},
{"subject":"Lab","grades":12}
]
我想这样分组和减少结果

//Expected Result
"Subjects":[
{"subject":"Math","grades":[1,2,3]},
{"subject":"Lab","grades":[10,12]}
]
我很好奇如何以java8风格映射和缩减对象。 我把过时的代码放在下面

我的主课

public static void main(String[] args)  {
List<Subject> list = new ArrayList<>();
list.add(new Subject("Math",1));
list.add(new Subject("Math",2));
list.add(new Subject("Math",3));
list.add(new Subject("Math",3));
list.add(new Subject("Lab",10));
list.add(new Subject("Lab",12));        
Map<String, Set<Integer>> result = new HashMap<>();
list.stream().forEach(subjects-> {
    if(result.get(subjects.getSubject())==null){
        Set<Integer> set = new HashSet<>();
        set.add(subjects.getGrades());
        result.put(subjects.getSubject(),set );
    }else{
        Set<Integer> set =result.get(subjects.getSubject());
        set.add(subjects.getGrades());
        result.put(subjects.getSubject(), set);
    }
    });

    result.forEach((key,val)->{
        System.out.println("KEY:"+key + " RESULT :"+val);
    });

}  


public class Subject {
private String subject;
private Integer grades;

public Subject(String subject , Integer grade) {
this.subject = subject;
this.grades = grade;
}

/** get set **/
}
publicstaticvoidmain(字符串[]args){
列表=新的ArrayList();
增加(新科目(“数学”,1));
增加(新科目(“数学”,2));
增加(新科目(“数学”,3));
增加(新科目(“数学”,3));
增加(新学科(“实验室”,10));
增加(新学科(“实验室”,12));
映射结果=新的HashMap();
list.stream().forEach(主题->{
if(result.get(subjects.getSubject())==null){
Set=newhashset();
set.add(subjects.getGrades());
result.put(subjects.getSubject(),set);
}否则{
Set=result.get(subjects.getSubject());
set.add(subjects.getGrades());
result.put(subjects.getSubject(),set);
}
});
结果。forEach((键,val)->{
System.out.println(“键:+KEY+”结果:+val);
});
}  
公共课科目{
私有字符串主题;
私人整数职系;
公共科目(字符串科目,整数等级){
this.subject=主语;
这个。等级=等级;
}
/**准备好**/
}

您可以使用
收集器.groupingBy(Subject::getSubject)
收集器.mapping(Subject::getGrades,Collectors.toSet())
作为下游

list.stream()
    .collect(Collectors.groupingBy(Subject::getSubject,
                 Collectors.mapping(Subject::getGrades, 
                     Collectors.toSet())));
它会给你一张
地图


注意:
result.put(subjects.getSubject(),set)行在后一种情况下是多余的。甚至主题也被复制
{Lab=[10, 12], Math=[1, 2, 3]}