JAVA List 按多个字段分组并求和

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

JAVA List GroupBy multiple fields and Sum

问题

我有一个包含字段Name、Currency和Amount的列表。
我想按Name、Currency分组,并计算Amount的总和。

我希望结果/输出是一个列表。

英文:

I have list having fields Name, Currency and Amount.
I want to group it by Name, Currency and Sum of Amount.

JAVA List 按多个字段分组并求和

List<myPojo> rows= ................

public class myPojo
{

    private String name;
    private String currency;
    private BigDecimal amount;

......................
}

I want result/output in list

答案1

得分: 2

你可以使用流API。
使用Collectors.toMap,并使用AbstractMap.SimpleEntry作为地图的键。然后为相同键的多个值定义合并函数。

List<myPojo> res = new ArrayList<>(rows.stream()
    .collect(Collectors.toMap(
        e -> new AbstractMap.SimpleEntry<>(e.getName(), e.getCurrency()),
        Function.identity(),
        (a, b) -> new myPojo(a.getName(), a.getCurrency(), a.getAmount().add(b.getAmount()))))
    .values());

演示:

List<myPojo> list = new ArrayList<>();
list.add(new myPojo("A", "USD", new BigDecimal(1.0)));
list.add(new myPojo("A", "USD", new BigDecimal(2.0)));
list.add(new myPojo("A", "USD", new BigDecimal(3.0)));
list.add(new myPojo("B", "USD", new BigDecimal(1.0)));
list.add(new myPojo("B", "USD", new BigDecimal(2.0)));
list.add(new myPojo("B", "USD", new BigDecimal(3.0)));
list.add(new myPojo("A", "US", new BigDecimal(1.0)));
list.add(new myPojo("A", "US", new BigDecimal(2.0)));
list.add(new myPojo("A", "US", new BigDecimal(3.0)));
List<myPojo> res = new ArrayList<>(list.stream()
    .collect(Collectors.toMap(
        e -> new AbstractMap.SimpleEntry<>(e.getName(), e.getCurrency()),
        Function.identity(),
        (a, b) -> new myPojo(a.getName(), a.getCurrency(), a.getAmount().add(b.getAmount()))))
    .values());
System.out.println(res.toString());

输出:

[myPojo [name=B, currency=USD, amount=6], 
myPojo [name=A, currency=USD, amount=6], 
myPojo [name=A, currency=US, amount=6]]

注意: 为了更好的约定,尝试将类的名称大写,如MyPojo

英文:

You can use Stream API.
Use Collectors.toMap and use AbstractMap.SimpleEntry as key of map. Then define merge function for multiple values of the same key.

List&lt;myPojo&gt; res = new ArrayList&lt;&gt;(rows.stream()
.collect(Collectors.toMap(
e -&gt; new AbstractMap.SimpleEntry&lt;&gt;(e.getName(), e.getCurrency()),
Function.identity(),
(a, b) -&gt; new myPojo(a.getName(), a.getCurrency(), a.getAmount().add(b.getAmount()))))
.values());

Demo:

List&lt;myPojo&gt; list = new ArrayList&lt;&gt;();
list.add(new myPojo(&quot;A&quot;, &quot;USD&quot;, new BigDecimal(1.0)));
list.add(new myPojo(&quot;A&quot;, &quot;USD&quot;, new BigDecimal(2.0)));
list.add(new myPojo(&quot;A&quot;, &quot;USD&quot;, new BigDecimal(3.0)));
list.add(new myPojo(&quot;B&quot;, &quot;USD&quot;, new BigDecimal(1.0)));
list.add(new myPojo(&quot;B&quot;, &quot;USD&quot;, new BigDecimal(2.0)));
list.add(new myPojo(&quot;B&quot;, &quot;USD&quot;, new BigDecimal(3.0)));
list.add(new myPojo(&quot;A&quot;, &quot;US&quot;, new BigDecimal(1.0)));
list.add(new myPojo(&quot;A&quot;, &quot;US&quot;, new BigDecimal(2.0)));
list.add(new myPojo(&quot;A&quot;, &quot;US&quot;, new BigDecimal(3.0)));
List&lt;myPojo&gt; res = new ArrayList&lt;&gt;(list.stream()
.collect(Collectors.toMap(
e -&gt; new AbstractMap.SimpleEntry&lt;&gt;(e.getName(), e.getCurrency()),
Function.identity(),
(a, b) -&gt; new myPojo(a.getName(), a.getCurrency(), a.getAmount().add(b.getAmount()))))
.values());
System.out.println(res.toString());

Output:

[myPojo [name=B, currency=USD, amount=6], 
myPojo [name=A, currency=USD, amount=6], 
myPojo [name=A, currency=US, amount=6]]

Note: Try to capitalize the name of the class like MyPojo for better convention

答案2

得分: 1

您可以使用groupingBy来生成一个Map&lt;String,Map&lt;String,BigDecimal&gt;&gt;,对应于Map&lt;Name,Map&lt;Currency,sum of Amount&gt;&gt;

List&lt;myPojo&gt; rows = List.of(new myPojo(&quot;ABCD&quot;, &quot;USD&quot;, new BigDecimal(20)),
                                new myPojo(&quot;XYZ&quot;,  &quot;GBP&quot;, new BigDecimal(60)),
                                new myPojo(&quot;XYZ&quot;,  &quot;THB&quot;, new BigDecimal(35)),
                                new myPojo(&quot;ABCD&quot;, &quot;INR&quot;, new BigDecimal(90)),
                                new myPojo(&quot;ABCD&quot;, &quot;USD&quot;, new BigDecimal(80)),
                                new myPojo(&quot;XYZ&quot;,  &quot;THB&quot;, new BigDecimal(45)));
        
Map&lt;String,Map&lt;String,BigDecimal&gt;&gt; map = 
            rows.stream()
            .collect(Collectors.groupingBy(myPojo::getName,
                    Collectors.groupingBy(myPojo::getCurrency,
                            Collectors.reducing(BigDecimal.ZERO, myPojo::getAmount, BigDecimal::add))));
System.out.println(map);

// 输出: {XYZ={GBP=60, THB=80}, ABCD={USD=100, INR=90}}

希望这个帮助!

英文:

You could use groupingBy to generate a Map&lt;String,Map&lt;String,BigDecimal&gt;&gt; corresponding to Map&lt;Name,Map&lt;Currency,sum of Amount&gt;&gt;

List&lt;myPojo&gt; rows = List.of(new myPojo(&quot;ABCD&quot;, &quot;USD&quot;, new BigDecimal(20)),
new myPojo(&quot;XYZ&quot;,  &quot;GBP&quot;, new BigDecimal(60)),
new myPojo(&quot;XYZ&quot;,  &quot;THB&quot;, new BigDecimal(35)),
new myPojo(&quot;ABCD&quot;, &quot;INR&quot;, new BigDecimal(90)),
new myPojo(&quot;ABCD&quot;, &quot;USD&quot;, new BigDecimal(80)),
new myPojo(&quot;XYZ&quot;,  &quot;THB&quot;, new BigDecimal(45)));
Map&lt;String,Map&lt;String,BigDecimal&gt;&gt; map = 
rows.stream()
.collect(Collectors.groupingBy(myPojo::getName,
Collectors.groupingBy(myPojo::getCurrency,
Collectors.reducing(BigDecimal.ZERO, myPojo::getAmount, BigDecimal::add))));
System.out.println(map);
// output: {XYZ={GBP=60, THB=80}, ABCD={USD=100, INR=90}}

huangapple
  • 本文由 发表于 2020年7月21日 19:14:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/63013283.html
匿名

发表评论

匿名网友

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

确定