根据流中的另一个字段汇总字段

Som*_*era 4 java grouping stream java-8

我有一个对象列表,如下所示:

{
    value=500
    category="GROCERY"
},
{
    value=300
    category="GROCERY"
},
{
    value=100
    category="FUEL"
},
{
    value=300
    category="SMALL APPLIANCE REPAIR"
},
{
    value=200
    category="FUEL"
}
Run Code Online (Sandbox Code Playgroud)

我想将其转换为如下所示的对象列表:

{
    value=800
    category="GROCERY"
},
{
    value=300
    category="FUEL"
},
{
    value=300
    category="SMALL APPLIANCE REPAIR"
}
Run Code Online (Sandbox Code Playgroud)

基本上将所有值添加到同一类别.

我应该使用flatMap吗?降低?我不明白这些的细微差别来弄明白.

救命?

编辑:

这个问题有一些密切的重复: Java 8 api流中是否有一个aggregateBy方法?Stream API的对象的Sum和属性

但在这两种情况下,最终结果都是地图,而不是列表

根据@AndrewTobilko和@JBNizet的回答,我使用的最终解决方案是:

List<MyClass> myClassList = list.stream()
    .collect(Collectors.groupingBy(YourClass::getCategory,
                    Collectors.summingInt(YourClass::getValue)))
    .entrySet().stream().map(e -> new MyClass(e.getKey(), e.getValue()).collect(toList());
Run Code Online (Sandbox Code Playgroud)

小智 5

Collectors类提供了一个"groupingBy",允许您对流执行"分组依据"操作(类似于数据库中的GROUP BY).假设您的对象列表是"对象"类型,以下代码应该起作用:

Map<String, Integer> valueByCategory = myObjects.stream().collect(Collectors.groupingBy(MyObjects::getCategory, Collectors.summingInt(MyObjects::getValue)));
Run Code Online (Sandbox Code Playgroud)

代码基本上按照每个类别对您的流进行分组,并在每个组上运行一个收集器,该收集器总结每个流元素的getValue()的返回值.请参阅https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html