Java 8 在一次迭代中求和两个对象属性

标签 java lambda foreach java-8 java-stream

我有一个 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);

//...
//Use creditTotal, debitTotal later

这看起来我正在遍历列表两次。有没有一种方法可以一次性完成这项工作,而不必两次处理 list ?

Java 8 之前的版本

BigDecimal creditTotal = BigDecimal.ZERO;
BigDecimal debitTotal = BigDecimal.ZERO;
for(LedgerEntry entry : ledgerEntries){
  creditTotal = creditTotal.add(entry.getCreditAmount());
  debitTotal = debitTotal.add(entry.getDebitAmount());
}

最佳答案

您可以减少到总计条目:

LedgerEntry totalsEntry = entries.stream().reduce(new LedgerEntry(), (te, e) -> {
    te.setCreditAmount(te.getCreditAmount().add(e.getCreditAmount()));
    te.setDebitAmount(te.getDebitAmount().add(e.getDebitAmount()));

    return te;
});

更新

在评论中正确地指出 reduce() 不应该修改初始标识符值,并且 collect() 应该用于可变归约。下面是一个使用 collect() 的版本(使用相同的 BiConsumer 作为累加器和组合器)。如果未设置 creditAmount 和/或 debitAmount 值,它还解决了潜在 NPE 的问题。

BiConsumer<LedgerEntry, LedgerEntry> ac = (e1, e2) -> {
    BigDecimal creditAmount = e1.getCreditAmount() != null ? e1.getCreditAmount() : BigDecimal.ZERO;
    BigDecimal debitAmount = e1.getDebitAmount() != null ? e1.getDebitAmount() : BigDecimal.ZERO;

    e1.setCreditAmount(creditAmount.add(e2.getCreditAmount()));
    e1.setDebitAmount(debitAmount.add(e2.getDebitAmount()));
};

LedgerEntry totalsEntry = entries.stream().collect(LedgerEntry::new, ac, ac);

突然之间,Java 8 之前的版本开始变得极具吸引力。

关于Java 8 在一次迭代中求和两个对象属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42386191/

相关文章:

PHP 关联数组。使用foreach获取键值对

java - 我可以从 java 层访问存储在 React Native 的 AsyncStorage 中的数据吗?

java - 如何从具有接口(interface)引用的类中获取简单的类名?

vb.net - 对于每个范围内不可用的每个变量

javascript - 使用 jquery 的 forEach 和 templatePlugin 追加 <div>

c++ - std::async 仅同步工作

java - 如何在java中将byte[]类型转换为Certificate类型?

java - 遇到 'Dead Link' 问题

java - 在日期属性为字符串的列表中查找具有最大日期的对象

c# - 没有 lambda 表达式的 Entity Framework 查询