我有一系列的 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?