我有下面的类:总结列表<X>列出<X>与Java 8个流API
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 | amount
---------------------
EUR | 47.1
USD | 4.09
我已经知道/ DID:
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());
谢谢。这与我所需要的很接近,但是你的代码给了我一个'Map'。是不是有可能找回一个'List'或者'Set'? (没有手动创建新的Money对象等) –
就在5分钟前,迭代entrySet的想法出现在我的脑海中,但我想:这真的很丑,必须有更性感/优雅的东西。 '---'但我认为你给出的答案是这样做的唯一方法。 ' - '现在我想:'moneyStream.collect(Collectors.groupingBy(m - > m.getCurrencyUnit());'然后用map生成'Map>'。 values()。stream()'产生一个'List '?! –