Search code examples
javahashmapjava-streambigdecimal

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


I have this stream where I get the "daily return" of each balance in the stream, but I want to get the product of all daily returns for each accountId. I know I need to put something like:

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

in, but I'm not sure how. Here is the stream so far:

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

Please feel free to suggest any way to get to this solution, and thank you!


Solution

  • To make it easier to follow, let's separate the computation of daily return from the stream:

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

    Now we can collect a product of all daily returns for each account using the 3-argument toMap collector:

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