簡體   English   中英

Java 流的總和為

[英]Java streams sum by

我有這樣的課:

@Data
@AllArgsConstructor
class AccountLink {
    private String code;
    private String account;
    private BigDecimal participation;
}

和這樣的列表:

        List<AccountLink> accountLinks = List.of(
                new AccountLink("001", "331", new BigDecimal(100)),
                new AccountLink("001", "332", new BigDecimal(100)),
                new AccountLink("001", "336", new BigDecimal(100)),
                new AccountLink("001", "678", new BigDecimal(100)),

                new AccountLink("002", "331", new BigDecimal(100)),
                new AccountLink("002", "332", new BigDecimal(100)),
                new AccountLink("002", "333", new BigDecimal(100)),
                new AccountLink("002", "334", new BigDecimal(100)),
                new AccountLink("002", "335", new BigDecimal(100)),
                new AccountLink("002", "336", new BigDecimal(100)),
                new AccountLink("002", "678", new BigDecimal(100)),

                new AccountLink("003", "331", new BigDecimal(100)),
                new AccountLink("003", "332", new BigDecimal(100)),
                new AccountLink("003", "333", new BigDecimal(100)),
                new AccountLink("003", "336", new BigDecimal(100)),
                new AccountLink("003", "678", new BigDecimal(100))
        );

我必須合計每個帳戶的參與,然后除以代碼總數(在此示例中為 3),輸出應如下所示:

331 - 100
332 - 100
333 - 66.6666
334 - 33.3333
335 - 33.3333
336 - 100
678 - 100

這是我為實現此目的而編寫的代碼:

        Map<String, Double> linksCalculation = new HashMap<>();
        Map<String, List<AccountLink>> linksPerAccount = accountLinks.stream()
                .collect(Collectors.groupingBy(AccountLink::getAccount));

        linksPerAccount.forEach((account, linksList) -> {
            linksCalculation.compute(account, (key, value) -> {
                BigDecimal sum = linksList.stream()
                        .map(AccountLink::getParticipation)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);

                if (value == null) value = 0d;
                value = Double.sum( value, sum.divide(new BigDecimal(3), 4, RoundingMode.DOWN).doubleValue() );
                return value;
            });
        });

linksCalculation 將正確顯示此信息。

但是,我想知道是否有更簡潔的方法可以使用 Java 流 API 來做到這一點。

一步完成此操作有點困難,因為您要執行兩種截然不同的計算。 但是,可以分兩步完成。 首先獲取代碼計數,然后將每個參與值除以該值,而不是等待除以總數。

long numCodes = accountLinks.stream().map(AccountLink::getCode).distinct().count();

Map<String, Double> linksCalculation = accountLinks.stream().collect(groupingBy(
        AccountLink::getAccount,
        reducing(
                0.0d,
                al -> al.getParticipation().doubleValue() / numCodes,
                Double::sum
        )
));

Collectors.reducing()確實是這里的關鍵。 參數是 (1) 初始值,(2) 為每個元素生成值的函數,以及 (3) 將新值與正在進行的縮減值(在本例中為總和)組合的函數。

為了保留您的BigDecimal計算,我按如下方式進行。 計算不同代碼的數量。

final long nCodes = accountLinks.stream().map(AccountLink::getCode).distinct().count();
  • 首先,使用Collectors.groupingBy作為帳號作為鍵
  • 然后使用Collectors.mapping從班級中拉出參與。
  • 然后使用Collectors.collectingAndThen
    • 首先將參與列表減少為一個總和
    • 然后應用整理功能除以nCodes
    • 然后返回結果的雙精度值。
Map<String, Double> linksCalculation = accountLinks.stream()
        .collect(Collectors.groupingBy(AccountLink::getAccount,
            Collectors.mapping(AccountLink::getParticipation,
              Collectors.collectingAndThen(
                Collectors.reducing(BigDecimal.ZERO,(sum, val) ->sum.add(val)),
                 sum -> sum.divide(BigDecimal.valueOf(nCodes),4,RoundingMode.DOWN)
                       .doubleValue()))));

linksCalculation.entrySet().forEach(System.out::println);

印刷

331=100.0
332=100.0
333=66.6666
334=33.3333
335=33.3333
336=100.0
678=100.0

groupingBy與下游收集器 ( summingDouble ) 一起使用:

final int n = (int) accountLinks.stream().map(a -> a.code).distinct().count();
         
Map<String, Double> result = accountLinks.stream()
    .collect(Collectors.groupingBy(
         a -> a.account, 
         Collectors.summingDouble(a -> a.participation.doubleValue() / n)
    ));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM