英文:
How do I create a new object from grouping by result
问题
// 在 https://stackoverflow.com/questions/61579954/java-8-pojo-objects-filter-pojo-based-on-common-multiple-key-combination-and-sum 的示例中
// 在求和后,我需要创建一个新的 Sales 类型的对象,其中包含总计(按分组求和的结果),类似于下面的内容
{
"month": "Total",
"year": "2000",
"state": "State1",
"city": "City1",
"sales": "15"
}
因此,我已经在 Sales 类中创建了相应的构造函数,并尝试了以下代码
list.stream()
.collect(groupingBy(Sale::getState,
groupingBy(Sale::getCity,
summingInt(Sale::getSales).Collectors.mapping(e -> new Sales("Total", "2000", "State1", "City1", <summingInt 的结果应该在这里>),
Collectors.toList()))));
我该如何在 Java 8 中实现类似上述格式的操作?
<details>
<summary>英文:</summary>
For the example in https://stackoverflow.com/questions/61579954/java-8-pojo-objects-filter-pojo-based-on-common-multiple-key-combination-and-sum
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 ?
</details>
# 答案1
**得分**: 1
你可以这样做:
在第二个`groupingBy`之处,你可以使用带有合并函数的`toMap`收集器。
```java
list.stream()
.collect(Collectors.groupingBy(Sales::getState,
Collectors.toMap(Sales::getCity, Function.identity(),
(s1, s2) -> new Sales(s1.month, ..., s1.getSales() + s2.getSales()))));
英文:
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()))));
答案2
得分: 1
你的方向是正确的。唯一需要完成的是最后一步,即将所有销售数据合并到一个对象中。你不能只使用 summingInt
,因为它只返回一个整数,而你没有其他字段来构造一个对象。你可以通过使用 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;
}))));
确保你的年份和月份在所有对象中都相同,否则会丢失(除非在这种情况下你不关心)。
英文:
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).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论