2017-02-22 1 views
5

J'ai un List<LedgerEntry> ledgerEntries et j'ai besoin de calculer la somme de creditAmount et debitAmount.Streams: Calculez la différence des totaux en une fois

class LedgerEntry{ 
private BigDecimal creditAmount; 
private BigDecimal debitAmount; 

//getters and setters 
} 

J'ai mis en œuvre ce que,

BigDecimal creditTotal = ledgeredEntries.stream().map(p ->p.getCreditAmount()). 
reduce(BigDecimal.ZERO, BigDecimal::add); 
BigDecimal debitTotal = ledgeredEntries.stream().map(p ->p.getDebitAmount()). 
reduce(BigDecimal.ZERO, BigDecimal::add); 
BigDecimal sumCreditDebit = creditTotal.subtract(debitTotal); 

Cela ressemble j'itérer sur la List deux fois. Y a-t-il un moyen de faire cela en une fois sans avoir à faire défiler la liste deux fois?

Répondre

4

Vous pouvez soustraire les montants individuels dans map puis sum les utiliser reduce

ledgerEntries.stream() 
    .map(e->e.getCreditAmount().subtract(e.getDebitAmount()) 
    .reduce(0,BigDecimal::add); 
+0

Merci. C'était rapide. Sur la même note, que se passe-t-il si j'ai besoin des deux valeurs séparément (à savoir: creditTotal et debitTotal séparément). – Krishan

+1

@Krishan Bienvenue. Pouvez-vous préciser ce que vous voulez dire en ayant besoin des deux valeurs séparément? – CKing

+0

Tout comme dans ma question, si j'ai besoin de valeurs de creditTotal et de debitTotal séparément pour pouvoir les utiliser plus tard, est-ce que je peux le faire en parcourant simplement la liste une fois? L'utilisation de stream() deux fois pour la même liste semble être répétée deux fois sur la liste? Ou n'est-ce pas le cas et le compilateur fait un peu de magie pour optimiser le streaming? – Krishan

6

Il suffit de le réduire à:

BigDecimal sumCreditDebit = ledgeredEntries.stream().map(p -> p.getCreditAmount() 
     .subtract(p.getDebitAmount())) 
     .reduce(BigDecimal.ZERO, BigDecimal::add); 
+1

* creditTotal.subtract (debitTotal); * ... – CKing

+1

@CKing C'était une faute de frappe ... Corrigé. – manouti

+1

Downvote rétractée. +1 – CKing

3
BigDecimal result = ledgeredEntries.stream().map(p -> p.getCreditAmount().subtract(p.getDebitAmount())) 
      .reduce(BigDecimal.ZERO, BigDecimal::add); 
+1

* creditTotal.subtract (debitTotal); ..... * – CKing

+1

Correction, merci – kamehl23

+0

Malheureusement, ceci est maintenant une toute nouvelle réponse à votre tentative initiale. Plus d'un repos que d'un correctif. – CKing

2

Voici ma solution:

BigDecimal result = array.stream().reduce(BigDecimal.ZERO, 
      (bigDecimal, ledgerEntry) -> bigDecimal.add(ledgerEntry.getCreditAmount()).subtract(ledgerEntry.getDebitAmount()), 
      BigDecimal::add); 

Je fais la différence entre chaque paire de cartes de crédit et je les additionne en utilisant reduce.