Warm tip: This article is reproduced from stackoverflow.com, please click
grouping java java-8 java-stream

grouping and sum with nested lists

发布于 2020-04-13 09:44:00

I have nested lists and I'm trying to group and sum to get the desired result using java streams and collectors . With this I'm not able to loop over multiple SubAccounts. Either I have to use for loop or some other logic. I want to achieve using streams api. Is there any possibility for that

Map<Long, BigDecimal> assetQuanMap = subAccounts.getAssets.parallelStream().collect(Collectors.groupingBy(Asset::getAssetId, Collectors.reducing(BigDecimal.ZERO, Asset::getQuantity, BigDecimal::add)));

I'm having the below classes or representation :

    Account
        SubAccount1
            Assets
                1 - 20
                2 - 30
                3 - 40
        SubAccount2
            Assets
                1 - 10
                2 - 5
                3 - 3
        SubAccount3

                1 - 3
                2 - 3
                3 - 4

Accounts class looks like :

Public class Account{
  List<SubAccounts> list;
}

Public Class SubAccounts    {
   List<Assets> list;
}

Public class Assets{
    Long assetId;
    BigDecimal quantity ;
}

I'm trying to get the result as below in Map . Basically for each of the subAccounts i need to group the assets at account level which looks similar to below

1 - 33
2 - 38
3 - 47
Questioner
sk27
Viewed
44
YCF_L 2019-03-26 02:45

You have to use two flatMap so you can group by assetId

Map<String, BigDecimal> collect = accounts.stream()
        .flatMap(account -> account.getList().stream())
        .flatMap(subAccount -> subAccount.getList().stream())
        .collect(Collectors.groupingBy(Assets::getAssetId,
                Collectors.reducing(
                        BigDecimal.ZERO, 
                        Assets::getQuantity,
                        BigDecimal::add)
        ));

from your code assetId is a String so the key of map should be a String, or you have to convert it, or change it in your class, like so :

Map<Long, BigDecimal> collect = accounts.stream()
        .flatMap(account -> account.getList().stream())
        .flatMap(subAccount -> subAccount.getList().stream())
        .collect(Collectors.groupingBy(asset -> Long.valueOf(asset.getAssetId()),
                Collectors.reducing(
                        BigDecimal.ZERO,
                        Assets::getQuantity,
                        BigDecimal::add
                )
        ));

Notes

  • don't use plurals in the name of classes;
  • don't name variable as list, use another significant name;
  • don't use assetId as a name of attribute instead use just use id;
  • don't use List in the name of variables assetList, instead use s in the end for example assets or accounts.