ich die folgende Klasse haben:Aggregate Liste <X><X> mit Java 8 Stream-API zur Liste
class Money {
CurrencyUnit currencyUnit;
BigDecimal amount;
}
In meiner Anwendung, erhalte ich eine zufällige Liste von Money
Objekte:
currencyUnit | amount
---------------------
EUR | 5.1
EUR | 0
USD | 1.09
EUR | 42
USD | 3
Jetzt Ich möchte die Java 8 Stream API verwenden, um das folgende Ergebnis zu erstellen (einfach BigDecimal::add
für jede Währung Unit aufrufen):
currencyUnit | amount
---------------------
EUR | 47.1
USD | 4.09
Was ich schon weiß/tat
Stream<Money> moneyStream = moneyList.stream();
Und hier endet es bereits. Ich weiß, ich kann eine Collector
verwenden ein Map<CurrencyUnit, List<Money>>
zu produzieren:
moneyStream.collect(Collectors.groupingBy(m -> m.getCurrencyUnit());
Aber dann gehe ich muss noch durch alle Schlüssel-Wert-Paare und die Menge Daten zusammenzufassen.
Was ist der richtige (und möglicherweise einfachste Weg), das zu tun? Es kann nicht so kompliziert sein, oder? :)
EDIT: Wenn es nicht so klar ist, was ich brauche, hier ist meine alte Art und Weise Java-Code:
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();
EDIT 2: Eine andere Lösung, die nicht wirklich elegant ist:
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());
Danke. Das ist nah an dem, was ich brauche, aber Ihr Code gibt mir eine 'Map'. Ist es nicht möglich, eine "Liste" oder ein "Set" zurück zu bekommen? (ohne manuell neue 'Money'-Objekte zu erstellen, etc.) –
Vor gerade einmal 5 Minuten kam mir die Idee, über den EintragSet zu denken, in den Sinn, aber ich dachte: Das ist wirklich hässlich, da muss etwas mehr sexy/elegant sein. »Aber ich denke, deine gegebene Antwort ist der einzige Weg, das zu tun. '---' genau jetzt dachte ich über: 'moneyStream.collect (Collectors.groupingBy (m -> m.getCurrencyUnit());' und dann benutze die generierte 'Map>' mit 'map. values (). stream() 'um eine' List ''! –