I have a class like this:
@Data
@AllArgsConstructor
class AccountLink {
private String code;
private String account;
private BigDecimal participation;
}
And a list like this:
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))
);
I have to total the participation for each account and then divide that by the total number of codes which is 3 in this example, the output should be like this:
331 - 100
332 - 100
333 - 66.6666
334 - 33.3333
335 - 33.3333
336 - 100
678 - 100
This is the code I wrote to achieve this:
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 would display this information correctly.
However, I'd like to know if there's a cleaner way to do this using Java streams API.