How do I create a new object from grouping by result

三世轮回 提交于 2020-05-17 05:58:13

问题


For the example in Java 8 POJO objects filter pojo based on common multiple key combination and sum on one field

After summing up, I need to create a new object of Sales type, having the totals ( sum result of group by ) Something like below

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

So i have created corresponding constructor in Sales and tried

list.stream()
    .collect(groupingBy(Sale::getState,
                        groupingBy(Sale::getCity,
                                   summingInt(Sale::getSales).Collectors.mapping(e -> new Sales ("Total","2000","State1","City1",<summingInt result should come here>),
                                Collectors.toList()))));  

How do I achieve something like above format in Java 8 ?


回答1:


Your direction is correct. The only thing needs to be done is the last step, which is combining all the sales number together into one object. You can't just use summingInt because it only returns an int and you don't have the other fields to construct an object. You can achieve this by using reduce to construct an initial object and adding the field value:

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()) ))));

If you don't care about month and year, you can also create an identity object (initial object) and add only sales to it. It can reduce the number of temporary objects created:

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;
                                   } ))));

Make sure your year and months are the same across all objects, or it will be lost (unless you don't care in this case).




回答2:


You can do like this:

instead of second groupingBy you can use toMap collector with merge function.

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


来源:https://stackoverflow.com/questions/61600799/how-do-i-create-a-new-object-from-grouping-by-result

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!