2017-02-22 10 views
5

У меня есть List<LedgerEntry> ledgerEntries и мне нужно рассчитать сумму creditAmount и debitAmount.Потоки: рассчитать разницу итогов за один раз

class LedgerEntry{ 
private BigDecimal creditAmount; 
private BigDecimal debitAmount; 

//getters and setters 
} 

Я реализовал это, как,

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); 

Это выглядит как я итерация над List дважды. Есть ли способ сделать это за один раз, не перепуская список дважды?

ответ

4

Вы можете вычесть отдельные суммы в map, а затем sum их с помощью reduce

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

Спасибо. Это было быстро. На том же примечании, что, если мне нужны два значения отдельно (то есть: creditTotal и debitTotal отдельно). – Krishan

+1

@Krishan Добро пожаловать. Можете ли вы рассказать о том, что вы подразумеваете, требуя двух значений отдельно? – CKing

+0

Как и в моем вопросе, если мне нужны значения creditTotal и debitTotal, которые будут использоваться позже, могу ли я сделать это, просто повторив список один раз? используя stream() дважды для одного и того же списка, похоже на повторение по списку дважды? Или это не так, и компилятор делает некоторую магию для оптимизации потоковой передачи? – Krishan

6

Просто уменьшить его:

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

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

+1

@CKing Это была опечатка ... Исправлено. – manouti

+1

Downvote втянута. +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

исправлено, спасибо – kamehl23

+0

К сожалению, теперь это совершенно новый ответ от вашей первоначальной попытки. Больше напоминаний, чем исправление. – CKing

2

Вот мое решение:

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

Я получаю разницу между каждой кредитной дебетовой парой и добавляю их вместе, используя reduce.

Смежные вопросы