首页 > 解决方案 > JAVA List GroupBy 多个字段和 Sum

问题描述

我有包含名称、货币和金额字段的列表。我想按名称、货币和金额总和对其进行分组。

这是样本数据和输出

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

public class myPojo
{

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

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

我想要列表中的结果/输出

标签: java

解决方案


您可以使用流 API。使用Collectors.toMapAbstractMap.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为了更好的约定,尽量将类名大写


推荐阅读