【问题标题】:How do you use stream operations to calculate an average of values within a list, omitting some?您如何使用流操作来计算列表中值的平均值,省略一些?
【发布时间】:2015-11-18 01:12:48
【问题描述】:

我有一个方法可以返回多个模型对象的属性平均值:

List<Activity> activities = ...;
double effortSum = 0;
double effortCount = 0;
activities.stream().forEach(a -> {
    double effort = a.getEffort();
    if (effort != Activity.NULL) {
        effortCount++;            < Compilation error, local variable
        effortSum += effort;      < Compilation error, local variable
    }
});

但是,如上所述,上述尝试无法编译。我想到的唯一解决方案是使用AtomicReferenceDouble 对象,但这看起来很笨拙,并且给应该简单的操作增加了大量的混乱。 (或者加番石榴,获得AtomicDouble,但得出同样的结论。)

是否有使用新的 Java 8 循环修改局部变量的“最佳实践”策略?

Activity的相关代码:

public class Activity {
    public static final double NULL = Double.MIN_VALUE;

    private double effort = NULL;

    public void setEffort(double effort) { this.effort = effort; }
    public double getEffort() { return this.effort; }

    ...
}

【问题讨论】:

  • 您能否在您的 OP 中包含 activities 的声明?
  • 当然,我添加了相关位。

标签: java foreach java-8


【解决方案1】:

是否有使用新的 Java 8 循环修改局部变量的“最佳实践”策略?

是的:不要。你可以修改它们的属性——尽管这仍然是个坏主意——但你不能自己修改它们;如果变量是 final 或可能是 final,则只能从 lambda 内部引用变量。 (AtomicDouble 确实是一种解决方案,另一种是 double[1],它只是作为一个持有者。)

这里实现“平均”操作的正确方法是

activities.stream()
    .mapToDouble(Activity::getEffort)
    .filter(effort -> effort != Activity.NULL)
    .average()
    .getAsDouble();

【讨论】:

  • 啊,完美 - 中间 filter() 方法正是让我摆脱了这个泡菜。
【解决方案2】:

在您的情况下,有一个功能更强大的解决方案 - 只需从流中计算汇总统计信息,您可以从中获取过滤的元素数量及其总和:

DoubleSummaryStatistics stats = 
    activities.stream()
              .mapToDouble(Activity::getEffort)
              .filter(e -> e != Activity.NULL)
              .summaryStatistics();

long effortCount = stats.getCount();
double effortSum = stats.getSum();

是否有修改局部变量的“最佳实践”策略 使用新的 Java 8 循环?

不要尝试这样做。我认为主要问题是人们试图以一种命令式的方式使用新的 Java 8 特性来翻译他们的代码(就像在你的问题中一样——然后你就有麻烦了!)。

首先尝试看看您是否可以提供一个实用的解决方案(我相信这是 Stream API 的目标)。

【讨论】:

  • 谢谢 - TIL 关于summaryStatistics() 以及。
  • 顺便说一句,我不会使用像double[1] 持有人这样的解决方法。将流并行转换为并发问题就足够了。我将让代码采用命令式风格。
猜你喜欢
  • 1970-01-01
  • 2020-12-19
  • 2015-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-25
相关资源
最近更新 更多