我有一个方法可以返回多个模型对象的属性平均值:
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
}
});
但是,如上所述,上述尝试无法编译。我遇到的唯一解决方案是使用AtomicReference
到Double
对象,但这看起来很苛刻,并且为应该是一个简单的操作添加了大量的混淆。 (或者添加番石榴并获得AtomicDouble
,但是得出了相同的结论。)
是否存在使用新Java 8循环修改局部变量的“最佳实践”策略?
活动的相关代码:
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; }
...
}
答案 0 :(得分:6)
是否有最佳实践&#34;使用新的Java 8循环修改局部变量的策略?
是的:不要。你可以修改他们的属性 - 虽然它仍然是一个坏主意 - 但你不能自己修改它们;你只能引用lambda中的变量,如果它们是final
或者可能是final
。 (AtomicDouble
确实是一个解决方案,另一个是double[1]
,只是作为持有者。)
实施&#34;平均值&#34;的正确方法这里的操作是
activities.stream()
.mapToDouble(Activity::getEffort)
.filter(effort -> effort != Activity.NULL)
.average()
.getAsDouble();
答案 1 :(得分:4)
在您的情况下,有一个功能更强大的解决方案 - 只需从流中计算摘要统计信息,您可以从中获取已过滤元素的数量及其总和:
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的目标)。