我有一系列的 double 值,我想对其求和并获得最大值。DoubleStream.summaryStatistics()听起来很完美。getSum()方法有一个API注释,使我想起了我在一门计算机科学类(class)中学到的知识:如果按绝对值对值求和,求和问题的稳定性往往会更好。但是,DoubleStream不允许我指定要使用的比较器,如果我在流上调用Double.compareTo,它将仅使用sorted()

因此,我将值收集到final Stream.Builder<Double> values = Stream.builder();中并调用

values.build()
    .sorted(Comparator.comparingDouble(Math::abs))
    .mapToDouble(a -> a).summaryStatistics();

但是,这看起来有些冗长,我宁愿使用DoubleStream.Builder而不是通用生成器。
我是否错过了某些内容,还是真的必须使用流的盒装版本才能指定比较器?

最佳答案

基本流没有重载的sorted方法,并且将以自然顺序进行排序。但是要回到您的根本问题,有一些方法可以提高总和的准确性,而无需先对数据进行排序。

一种此类算法是Kahan summation algorithm,碰巧被OpenJDK/Oracle JDK internally使用。

公认的是,这是一个实现细节,因此通常需要注意(非OpenJDK/Oracle JDK或将来的OpenJDK JDK可能会采用其他方法等)。

另请参阅此帖子:In which order should floats be added to get the most precise result?

09-28 12:51