我在lambdas上遇到了一个小问题。 如何遍历它并在每次迭代时向我的变量 currentLateAmountDouble 添加值?
BigDecimal currentLateAmountDouble = BigDecimal.ZERO;
Collection<VPO> lines = BO_Contract.getLines(trxName, contractVPO.getID(), RContractLine.LineNo + " ASC ", ctx);
if (lines != null && !lines.isEmpty()) {
if (lines.stream()
.filter(line -> onDate.compareTo(line.getDateValue(RContractLine.TermDate)) > 0) != null) {
lines.forEach(line -> currentLateAmountDouble = currentLateAmountDouble.add(NumberUtils.getAmount(line.getDoubleValue(RContractLine.TotalAmountOpen))));
}
}
它在第 5 行给我一个错误:
局部变量 currentLateAmount在封闭作用域中定义的双精度必须是最终的或有效的最终的
Java 7 中的相同方法(有效):
BigDecimal currentLateAmountDouble = BigDecimal.ZERO;
Collection<VPO> lines = BO_Contract.getLines(trxName, contractVPO.getID(), RContractLine.LineNo + " ASC ", ctx);
if (lines != null && !lines.isEmpty()) {
for (VPO line : lines) {
if (onDate.compareTo(line.getDateValue(RContractLine.TermDate)) > 0) {
currentLateAmountDouble = currentLateAmountDouble.add(NumberUtils.getAmount(line.getDoubleValue(RContractLine.TotalAmountOpen)));
}
}
}
编辑:解决了!使用@JBNizet解决方案并这样做:
currentLateAmountDouble = lines.stream().filter(line -> onDate.compareTo(line.getDateValue(RContractLine.TermDate)) > 0)
.map(line -> NumberUtils.getAmount(line.getDoubleValue(RContractLine.TotalAmountOpen))).reduce(BigDecimal.ZERO, BigDecimal::add);
正如错误消息所说,您不能从 lambda 重新分配外部局部变量(就像在 Java 7 中从匿名类重新分配一样)。
尝试从功能操作修改外部状态是一种代码异味。但是您的操作只是一个映射,然后是归约操作:您将每个元素转换为 BigDecimal,然后将所有 BigDecimal 求和:
BigDecimal currentLateAmountDouble =
lines.stream()
.map(line -> NumberUtils.getAmount(line.getDoubleValue(RContractLine.TotalAmountOpen)))
.reduce(BigDecimal.ZERO, BigDecimal::add);
请注意,将 filter()
的结果与 null 进行比较的测试没有意义:filter()
永远不会返回 null。您可能正在这里寻找anyMatch
。
你需要使用一个减少函数...
在您的 if 语句中尝试此操作...
currentLateAmountDouble = lines.stream().mapToInt(l->NumberUtils.getAmount(l.getDoubleValue( RContractLine.TotalAmountOpen)).sum();
这可能不准确,我不是用电脑来测试这个,但应该让你足够接近。
另请参阅 https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html 以供参考