问题
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