Java 流,如何 GROUP BY 并找到流的产品

Java stream, how to GROUP BY and find product of stream

我有这个流,我可以在其中获取流中每个余额的 "daily return",但我想获取每个 accountId 的所有每日 returns 的乘积。我知道我需要输入类似的内容:

.collect(Collectors.groupingBy(n -> n.getAccountId(), Collectors.reducing(BigDecimal.ZERO, BigDecimal::multiply)));

在,但我不确定如何。这是目前的流:

Map<Long, Double> solution = new HashMap<Long, Double>();

balances.stream()
          .forEach(n -> {
              if(n.getCashflow().compareTo(BigDecimal.ZERO) > 0) {
                  solution.put(n.getAccountId(), n.getEndingBalance().divide((n.getStartingBalance().add(n.getCashflow())), 6, RoundingMode.FLOOR).doubleValue());
              }
              else {
                  solution.put(n.getAccountId(), (n.getEndingBalance().subtract(n.getCashflow())).divide(n.getStartingBalance(), 6, RoundingMode.FLOOR).doubleValue());
              }
              });

请随时提出解决此问题的方法,谢谢!

为了更容易理解,让我们将每日 return 的计算与流分开:

Function<Balance, BigDecimal> dailyReturn = n -> {
    if (...) {  
        return ...;
    } else {
        return ...;
    }
};   // or use a ternary statement

现在我们可以使用 3 参数 toMap 收集器为每个帐户收集所有每日 return 的产品:

balances.stream().collect(Collectors.toMap(
    Balance::getAccountId, 
    dailyReturn, 
    BigDecimal::multiply
));
public class Balance {

  private Long accountId;
  private BigDecimal cashflow;
  private BigDecimal startingBalance;
  private BigDecimal endingBalance;
}

List<Balance> balances = new ArrayList<>();

Map<Long, Double> solution2 = balances.stream().map(n -> {
    BigDecimal bd;
    if (n.getCashflow().compareTo(BigDecimal.ZERO) > 0) {
        bd = n.getEndingBalance()
            .divide(n.getStartingBalance().add(n.getCashflow()), 
                            6, RoundingMode.FLOOR);
    } else {
        bd = (n.getEndingBalance().subtract(n.getCashflow()))
                .divide(n.getStartingBalance(), 6,
                    RoundingMode.FLOOR);
    }
    return new SimpleEntry<Long, Double>(n.getAccountId(), bd.doubleValue());
}).collect(Collectors.groupingBy(Entry::getKey, 
        Collectors.reducing(1d, Entry::getValue, (d1, d2) -> d1 * d2)));

System.out.println(solution2);