Ho la seguente classe:Lista Aggregate <X> to List <X> con Java 8 API flusso
class Money {
CurrencyUnit currencyUnit;
BigDecimal amount;
}
Nella mia applicazione, ottengo qualche lista casuale di oggetti Money
:
currencyUnit | amount
---------------------
EUR | 5.1
EUR | 0
USD | 1.09
EUR | 42
USD | 3
Ora Mi piacerebbe utilizzare l'API Java 8 Stream per creare il seguente risultato (chiamando semplicemente BigDecimal::add
per ogni importo di valutaUnit):
currencyUnit | amount
---------------------
EUR | 47.1
USD | 4.09
quello che già so/DID:
Stream<Money> moneyStream = moneyList.stream();
E qui finisce già. So che posso utilizzare un Collector
per produrre un Map<CurrencyUnit, List<Money>>
:
moneyStream.collect(Collectors.groupingBy(m -> m.getCurrencyUnit());
Ma poi devo ancora passare attraverso tutti valore di coppie di chiavi e riassumere la quantità di dati.
Qual è il giusto (e forse il modo più semplice) per farlo? Non può essere così complicato, giusto? :)
EDIT: Se non è chiaro quello che mi serve, ecco il mio vecchio modo di codice 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();
EDIT 2: Un'altra soluzione, che non è davvero elegante:
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());
Grazie. È vicino a ciò di cui ho bisogno, ma il tuo codice mi dà una 'Mappa'. Non è possibile recuperare un 'List' o un' Set'? (senza creare manualmente nuovi oggetti 'Money', ecc.) –
Solo 5 minuti fa mi è venuta in mente l'idea di scorrere l'entryset, ma ho pensato: è davvero brutto, deve esserci qualcosa di più sexy/elegante. '---' Ma penso che la tua risposta data sia l'unico modo per farlo. '---' proprio ora pensavo a: 'moneyStream.collect (Collectors.groupingBy (m -> m.getCurrencyUnit());' e quindi usa la 'Mappa Map CurrencyUnit, List>' con 'map. values (). stream() 'per produrre un' Elenco '?! –