Java流,如何GROUP BY和查找流的产品

时间:2018-01-18 18:49:16

标签: java hashmap java-stream bigdecimal

我有这个流,我在流中获得每个余额的“每日回报”,但我希望得到每个accountId的所有每日回报的乘积。我知道我需要做类似的事情:

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

in,但我不确定如何。到目前为止,这是流:

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());
              }
              });

请随时建议任何方式来解决此问题,谢谢!

2 个答案:

答案 0 :(得分:2)

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

UpdatePanel1

现在我们可以使用3参数Function<Balance, BigDecimal> dailyReturn = n -> { if (...) { return ...; } else { return ...; } }; // or use a ternary statement 收集器收集每个帐户的所有每日回报的产品:

toMap

答案 1 :(得分:0)

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);