如何根据结果分组创建新对象

时间:2020-05-04 20:13:31

标签: java java-8 grouping

对于Java 8 POJO objects filter pojo based on common multiple key combination and sum on one field

中的示例

总结之后,我需要创建一个Sales类型的新对象,其总和(group by的总和)如下所示

set logging on
b func2
commands
silent
bt 1
continue
end
b func1
commands
silent
bt 1
set logging off
continue
end

所以我在Sales中创建了相应的构造函数并尝试了

{
"month" : "Total",
"year":  "2000",
"state" : "State1",
"city" :  "City1",
"sales" : "15"
}

如何在Java 8中实现上述格式?

2 个答案:

答案 0 :(得分:1)

您可以这样做:

您可以将groupingBy收集器与合并功能一起使用,而不是第二toMap

list.stream()
    .collect(Collectors.groupingBy(Sales::getState,
        Collectors.toMap(Sales::getCity,Function.identity(),                              
              (s1, s2) -> new Sales(s1.month,...,s1.getSales() + s2.getSales()))));

答案 1 :(得分:1)

您的方向正确。唯一需要做的是最后一步,即将所有销售编号组合到一个对象中。您不能仅使用summingInt,因为它仅返回一个int,并且您没有其他字段来构造对象。您可以通过使用reduce构造一个初始对象并添加字段值来实现此目的:

list.stream()
    .collect(groupingBy(Sale::getState,
                        groupingBy(Sale::getCity,
                                   reducing( (a, b) -> new Sale(a.getMonth(), a.getYear(), a.getState(), a.getCity(), a.getSale() + b.getSale()) ))));

如果您不在乎月份和年份,则还可以创建一个标识对象(初始对象),并仅向其中添加销售额。它可以减少创建的临时对象的数量:

list.stream()
    .collect(groupingBy(Sale::getState,
                        groupingBy(Sale::getCity,
                                   reducing(new Sale("Total", "2000", "", "", 0), (a, b) -> {
                                            a.setState(b.getState());
                                            a.setCity(b.getCity()); 
                                            a.setSales(a.getSales() + b.getSales()); 
                                            return a;
                                   } ))));

确保所有对象的年份和月份都相同,否则将会丢失(除非您不在乎这种情况)。

相关问题