首页 > 解决方案 > Collectors.averagingInt - 这是一个运行平均值还是将所有以前的数字保留在内存中?

问题描述

在下面的代码中,平均是作为运行平均值工作还是将所有先前的整数保留在内存中并每次重新计算平均值?我想要的是一个运行平均值,因为文件中的整数数量可能非常大(所以我不希望它们都保存在内存中),但另一个开发人员指出第四行实际上可能会尝试将所有整数保存在内存中并每次重新计算平均值。哪一个是正确的?谢谢

return Files.readAllLines(Paths.get(fileName)).stream()
        .flatMap(n -> Arrays.stream(n.split(" ")))
        .map(Integer::valueOf)
        .collect(Collectors.averagingInt(Integer::intValue));

标签: javajava-8streamjava-stream

解决方案


平均收集器不需要将其平均的所有数字保存在内存中:它只需要跟踪元素的总和和计数,然后在最后除以得出平均值。

因此,从文件中读取多少内容并不重要:用于计算平均值的空间是恒定的。


Effective Java 3rd Edition,第 214 页有一点,它说您应该只使用某些收集器作为下游收集器 -Collectors.averagingInt就是这样的收集器。您不需要将这些收集器用作“主要”(如果这是正确的术语)收集器,因为相同的功能可直接在流的 API 上使用。

更正确的方法是使用IntStream,它有一个average()方法:

return Files.readAllLines(Paths.get(fileName)).stream()
        .flatMap(n -> Arrays.stream(n.split(" ")))
        .mapToInt(Integer::parseInt)
        .average()   // Returns an OptionalDouble
        .orElse(0);  // averagingInt returns 0 if the stream is empty.

推荐阅读