mapToDouble() 是否真的需要对 List<Double> 求和?使用 Java 8 流? [英] Is mapToDouble() really necessary for summing a List&lt;Double&gt; with Java 8 streams?

查看:45
本文介绍了mapToDouble() 是否真的需要对 List<Double> 求和?使用 Java 8 流?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,使用 Java 8 流对 List 求和的方法是这样的:

As far as I can tell, the way to sum a List<Double> using Java 8 streams is this:

List<Double> vals = . . . ;
double sum = vals.stream().mapToDouble(Double::doubleValue).sum();

对我来说,mapToDouble(Double::doubleValue) 似乎有点笨拙 - 只是 lambdas 和流应该免除的那种样板仪式".

To me, the mapToDouble(Double::doubleValue) seems kind of crufty - just the sort of boilerplate "ceremony" that lambdas and streams were supposed to dispense with.

最佳实践告诉我们更喜欢 List 实例而不是数组,但对于这种求和,数组似乎更清晰:

Best practices tell us to prefer List instances over arrays, and yet for this sort of summing, arrays seem cleaner:

double[] vals = . . . ;
double sum = Arrays.stream(vals).sum();

当然,可以这样做:

List<Double> vals = . . . ;
double sum = vals.stream().reduce(0.0, (i,j) -> i+j);

但是 reduce(....)sum() 长很多.

But that reduce(....) is so much longer than sum().

我知道这与需要围绕 Java 的非对象原语改造流的方式有关,但是,我是否在这里遗漏了什么?有没有办法挤压自动装箱以缩短它?或者这只是目前最先进的技术?

I get that this has to do with the way streams need to be retrofitted around the Java's non-object primitives, but still, am I missing something here? Is there some way to squeeze autoboxing in to make this shorter? Or is this just the current state of the art?

以下是答案摘要.虽然我在这里有一个摘要,但我敦促读者自己完整地阅读答案.

Here is a digest of answers below. While I have a summary here, I urge the reader to peruse the answers themselves in full.

@dasblinkenlight 解释说,由于 Java 历史上更早的决定,特别是泛型的实现方式及其与非对象原语的关系,某种类型的拆箱总是必要的.他指出,理论上编译器可以直观地进行拆箱并允许使用更简短的代码,但这尚未实现.

@dasblinkenlight explains that some kind of unboxing will always be necessary, due to decisions made further back in the history of Java, specifically in the way generics were implemented and their relationship to the non-object primitives. He notes that it is theoretically possible for the compiler to intuit the unboxing and allow for briefer code, but this has not yet been implemented.

@Holger 展示了一个与我所询问的表现力非常接近的解决方案:

@Holger shows a solution that is very close to the expressiveness I was asking about:

double sum = vals.stream().reduce(0.0, Double::sum);

我不知道新的静态 Double.sum() 方法.添加了 1.8,它似乎是为了我所描述的目的.我还发现了 Double.min()Double.max().展望未来,我肯定会在 List 和类似的操作中使用这个习语.

I was unaware of the new static Double.sum() method. Added with 1.8, it seems intended for the very purpose I was describing. I also found Double.min() and Double.max(). Going forward, I will definitely use this idiom for such operations on List<Double> and similar.

推荐答案

对我来说,mapToDouble(Double::doubleValue) 似乎 [什么] lambdas 和流应该免除.

To me, the mapToDouble(Double::doubleValue) seems [what] lambdas and streams were supposed to dispense with.

需要使用 mapToDouble 是决定通过类型擦除实现泛型的结果,基本上关闭了在泛型中使用基元的任何可能性的大门.正是这个决定使得有必要创建 DoubleStreamIntStreamLongStream 类系列 - 以提供基于流的拆箱.

The need to use mapToDouble is a consequence of a decision to implement generics via type erasure, essentially closing the door on any possibility of using primitives inside generics. It is that same decision that made it necessary to create the DoubleStream, IntStream, and LongStream family of classes - to provide a stream-based unboxing.

有什么方法可以压缩自动装箱以使其更短吗?或者这只是目前最先进的技术?

Is there some way to squeeze autoboxing in to make this shorter? Or is this just the current state of the art?

不幸的是,现在不是:虽然理论上编译器可以确定 Stream 可以隐式转换为 DoubleStream原语未装箱的方式,这尚未完成.

Unfortunately, not at this time: although it is theoretically possible for the compiler to figure out that Stream<Double> can be converted to DoubleStream implicitly, in the same way that the primitives are unboxed, this has not been done.

就基于阵列的解决方案而言,它是三者中效率最高的.但是,它不如其他两个灵活:带有 mapToDouble 的一个允许您对自定义类的任何属性求和,而最后一个允许您执行其他类型的聚合.

As far as your array-based solution goes, it is the most efficient of the three. However, it is not as flexible as the other two: the one with mapToDouble lets you sum any attribute of a custom class, while the last one lets you perform other types of aggregation.

reduce(....)sum()

我同意,这种方法在可读性方面比 mapToDouble 差.

I agree, this approach is worse than mapToDouble in terms of readability.

这篇关于mapToDouble() 是否真的需要对 List<Double> 求和?使用 Java 8 流?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆