У меня есть следующий класс:
class Money {
CurrencyUnit currencyUnit;
BigDecimal amount;
}
В моем приложении я получаю случайный список Money объектов:
currencyUnit | amount
---------------------
EUR | 5.1
EUR | 0
USD | 1.09
EUR | 42
USD | 3
Теперь я хотел бы использовать Java 8 Stream API для создания следующего результата (просто вызывая BigDecimal::add для каждой суммы currencyUnit):
currencyUnit | amount
---------------------
EUR | 47.1
USD | 4.09
Что я уже знаю/делал:
Stream<Money> moneyStream = moneyList.stream();
И вот оно уже заканчивается. Я знаю, что могу использовать Collector для создания Map<CurrencyUnit, List<Money>>:
moneyStream.collect(Collectors.groupingBy(m -> m.getCurrencyUnit());
Но тогда мне все равно придется пройтись по всем парам ключ-значение и просуммировать данные суммы.
Как правильно (и, возможно, проще всего) это сделать? Это не может быть так сложно, верно? :)
РЕДАКТИРОВАТЬ: Если не совсем понятно, что мне нужно, вот мой старый Java-код:
Map<CurrencyUnit, Money> map = new HashMap<>();
moneyList.stream().forEach(e -> {
Money m = map.get(e.getCurrencyUnit());
if(m == null) {
m = new Money();
m.setAmount(BigDecimal.ZERO);
m.setCurrencyUnit(e.getCurrencyUnit());
map.put(e.getCurrencyUnit(), m);
}
m.setAmount(m.getAmount().add(e.getAmount()));
});
return map.values();
РЕДАКТИРОВАТЬ 2: Другое решение, которое не очень элегантно:
List<Money> list = inputList.stream()
.collect(Collectors.groupingBy(Money::getCurrencyUnit))
.values().stream().map(ml -> {
Money money = new Money();
ml.forEach(m -> {
if(money.getCurrencyUnit() == null) {
money.setCurrencyUnit(m.getCurrencyUnit());
money.setAmount(m.getAmount());
} else {
money.setAmount(money.getAmount().add(m.getAmount()));
}
});
return money;
}).collect(Collectors.toList());