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

huangapple go评论65阅读模式
英文:

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) -&gt; 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) -&gt; 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(&quot;Total&quot;, &quot;2000&quot;, &quot;&quot;, &quot;&quot;, 0), (a, b) -&gt; {
                                            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).

huangapple
  • 本文由 发表于 2020年5月5日 04:13:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/61600799.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定