【问题标题】:JAVA List GroupBy multiple fields and SumJAVA List GroupBy 多个字段和 Sum
【发布时间】:2020-07-21 11:14:28
【问题描述】:

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

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

public class myPojo
{

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

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

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

【问题讨论】:

标签: java


【解决方案1】:

您可以使用 Stream API。 使用Collectors.toMap 并使用AbstractMap.SimpleEntry 作为地图的键。然后为同一个key的多个值定义合并函数。

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,以便更好地约定

【讨论】:

  • 如果 myPojo 没有构造函数怎么办。那么如何获取这些值
  • 然后创建一个构造函数,没有构造函数你如何设置值?如果没有构造函数,则需要使用 setter 设置每个值。喜欢(a,b) -&gt; {myPojo p = new myPojo(); p.setName(a.getName());..... return p;
  • 另一种方法是(a, b) -&gt; { a.setAmount(a.getAmount().add(b.getAmount())); return a;})),但它会模仿您当前的列表
  • @ShivprsadSammbhare 你的问题解决了吗?随时寻求帮助
【解决方案2】:

您可以使用 groupingBy 生成与Map&lt;Name,Map&lt;Currency,sum of Amount&gt;&gt; 对应的Map&lt;String,Map&lt;String,BigDecimal&gt;&gt;

List<myPojo> rows = List.of(new myPojo("ABCD", "USD", new BigDecimal(20)),
                            new myPojo("XYZ",  "GBP", new BigDecimal(60)),
                            new myPojo("XYZ",  "THB", new BigDecimal(35)),
                            new myPojo("ABCD", "INR", new BigDecimal(90)),
                            new myPojo("ABCD", "USD", new BigDecimal(80)),
                            new myPojo("XYZ",  "THB", new BigDecimal(45)));
    
Map<String,Map<String,BigDecimal>> 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}}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-12
    • 2020-05-19
    相关资源
    最近更新 更多