【问题标题】:Java 8 lambda aggregateJava 8 lambda 聚合
【发布时间】:2016-03-07 16:45:35
【问题描述】:

我在使用 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 行给了我一个错误:

在封闭范围内定义的局部变量 currentLateAmountDouble 必须是 final 或有效 final

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

【问题讨论】:

    标签: java for-loop lambda


    【解决方案1】:

    正如错误消息所说,您不能从 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

    【讨论】:

      【解决方案2】:

      你需要使用归约函数...

      在你的 if 语句中试试这个...

      currentLateAmountDouble  = lines.stream().mapToInt(l->NumberUtils.getAmount(l.getDoubleValue( RContractLine.TotalAmountOpen)).sum();
      

      这可能不准确,我不是通过电脑来测试这个,但应该让你足够接近。

      另外,请参阅https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html 以供参考

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-10
        • 2017-09-26
        • 1970-01-01
        相关资源
        最近更新 更多