为什么java收集流每次运行两次getter?

R H*_*tra 9 java performance java-8 java-stream collectors

我有一个带有项目的List,其中每个项目都是一个对象,我有一个我感兴趣的getter方法.我想在完整列表上运行以总结所有这些getter结果.

当我使用java 8流时,它看起来像这样:

double currentProduction = itemList.stream().collect(
    Collectors.summingDouble((e) -> e.getProduction(param)));
Run Code Online (Sandbox Code Playgroud)

在普通的旧java中,它看起来像这样:

for (Item item : itemList) {
    currentProduction += item.getProduction(param);
}
Run Code Online (Sandbox Code Playgroud)

两种方法产生完全相同的结果,但我的记录器报告,对于每个项目实例,在java 8流解决方案的情况下,getProduction()方法运行TWICE.在普通的旧java列表迭代解决方案中,getProduction方法只是按预期运行一次.

由于getProduction方法成本很高,这对我来说是一个问题.

为什么是这样?我能做些什么(除了只使用for循环)?

tal*_*lex 12

这是实施中的错误Collectors.summingDouble.

你可以itemList.stream().mapToDouble(Class1::getProduction).sum()改用.

bug的详细信息:

Collector实施来源.

    return new CollectorImpl<>(
            () -> new double[3],
            (a, t) -> { sumWithCompensation(a, **mapper.applyAsDouble(t)**);
                        a[2] += **mapper.applyAsDouble(t)**;},
            (a, b) -> { sumWithCompensation(a, b[0]);
                        a[2] += b[2];
                        return sumWithCompensation(a, b[1]); },
            a -> computeFinalSum(a),
            CH_NOID);
Run Code Online (Sandbox Code Playgroud)

错误标记为**.他们mapper.applyAsDouble(t)两次调用.

  • 我不知道已经找到,修复并修复了错误.我认为提供源代码足以证明我的主张. (2认同)