简体   繁体   English

Java 8 Streams - 为什么我不能对整数流求和?

[英]Java 8 Streams - Why can't I sum a Stream of Integers?

Given a list of Integer's: List<Integer> numbers = Arrays.asList(1,2,3); 给出一个Integer的List<Integer> numbers = Arrays.asList(1,2,3);List<Integer> numbers = Arrays.asList(1,2,3);

Why can't I sum them like: numbers.stream().sum(); 为什么我不能将它们总结为: numbers.stream().sum(); ?

Instead I have to do this: numbers.stream().mapToInt(e -> e).sum(); 相反,我必须这样做: numbers.stream().mapToInt(e -> e).sum();

I know that mapToInt produces an IntStream , the primitive specialization. 我知道mapToInt生成一个IntStream ,即原始特化。 But still I don't get it. 但我仍然没有得到它。 Why can't it sum Integers? 为什么它不能和整数相加? I know that this list has Integers and the compiler should be able to do the same. 我知道这个列表有整数,编译器也应该能够做到这一点。 After all it can now infer type parameters in lambda expressions. 毕竟它现在可以推断lambda表达式中的类型参数。

OK, an Integer could be null and sum would fail. 好的,一个Integer可能为null,sum也会失败。 But I could take responsibility for that and filter null out: 但我可以对此负责并过滤掉null:

numbers.stream().filter(Objects::nonNull).sum();

Why can't I sum a Stream of Integers? 为什么我不能总结整数流?

Calling stream() on a List will get you a general-purpose Stream , which can handle any reference type, not just numeric types. List上调用stream()将为您提供通用Stream ,它可以处理任何引用类型,而不仅仅是数字类型。 It doesn't make sense to include a sum method on Stream , because it doesn't make sense to sum URL s, Class es, Thread s, or any other non-numeric reference type. Stream上包含sum方法没有意义,因为对URL s, Class es, Thread s或任何其他非数字引用类型求和没有意义。

You could sum the elements by calling reduce : 您可以通过调用reduce对元素求和:

numbers.stream().reduce(0, (a, b) -> a + b)

But that would involve a lot of unboxing and boxing. 但这将涉及很多拆箱和拳击。 It would be best to sum them as you have it, by converting it to an IntStream , which operates on int s, and calling sum() (or summaryStatistics() , which includes count, average, max, and min along with sum). 最好通过将它们转换为IntStream来对它们进行IntStream ,它可以在int上运行,并调用sum() (或summaryStatistics() ,其中包括count,average,max和min以及sum) 。

You could even use IntStream.of and avoid boxing the values even once. 你甚至可以使用IntStream.of并避免装箱值甚至一次。

IntStream.of(1, 2, 3).sum()

Stream<Interger> and IntStream are actually different. Stream<Interger> IntStream Stream<Interger>IntStream实际上是不同的。 As numbers.stream() returns an object of Type Stream and Stream interface does not have any method like sum . 由于numbers.stream()返回Type Stream的对象, Stream接口没有像sum这样的方法。 Another side numbers.stream().mapToInt(e -> e) returns IntStream which has the sum method. 另一边是numbers.stream().mapToInt(e -> e)返回具有sum方法的IntStream

You cannot do: 你做不到:

numbers.stream().sum();

because Stream<T> is a generic type and as far as it's concerned it's dealing with any type of object. 因为Stream<T>是一种泛型类型,并且只要涉及到它处理任何类型的对象。 eg that could be Stream<Person> , Stream<Apple> etc. hence doesn't make sense to include a sum method. 例如,可能是Stream<Person>Stream<Apple>等因此包含sum方法没有意义。

I think that what you are asking for can not be done at all, even theoretically. 我认为你要求的东西根本无法完成,甚至理论上也是如此。

I mean stream() is declared on the List interface and it returns Stream<E> . 我的意思是在List接口上声明了stream() ,它返回Stream<E> You know that E is actually an Integer , the compiler has to infer that, and it's not like the compiler can change the return type when it infers the type, you are still going to get a general Stream<E> . 知道E实际上是一个Integer ,编译器必须推断它,并且它不像编译器在推断类型时可以改变返回类型,你仍然会得到一个通用的Stream<E>

But this is even worse if I think about it more, in such a case there would have to be a BaseStream returned that both Stream<String> and IntStream would extend, and sum for a Stream<String> makes no sense. 但是如果我更多地考虑它会更糟糕,在这种情况下,必须返回一个BaseStreamStream<String>IntStream都会扩展,而Stream<String> sum没有意义。 Later E type would have to be preserved at runtime, so that you know what specialization to return and this is obviously not possible (well not without a useless witness that is) 以后E类型必须在运行时保留,以便你知道返回什么专业化,这显然是不可能的(好吧,没有无用的见证)

If there were a IntsList that a theoretical IntsArray.asIntsList would return, this would have been indeed possible, but what a mess this would become in such a case. 如果有一个理论上的IntsArray.asIntsList会返回一个IntsList ,那么这确实是可能的,但在这种情况下会变得多么混乱。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM