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

时间:2022-06-23 12:02:52

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

给出一个Integer的列表:List 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. 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.

我知道mapToInt生成一个IntStream,即原始特化。但我仍然没有得到它。为什么它不能和整数相加?我知道这个列表有整数,编译器也应该能够做到这一点。毕竟它现在可以推断lambda表达式中的类型参数。

OK, an Integer could be null and sum would fail. But I could take responsibility for that and filter null out:

好的,一个Integer可能为null,sum也会失败。但是我可以对此负责并过滤掉null:

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

。numbers.stream()滤波器(对象::非空)的.sum();

Why can't I sum a Stream of Integers?

为什么我不能总结整数流?

4 个解决方案

#1


14  

Calling stream() on a List will get you a general-purpose Stream, which can handle any reference type, not just numeric types. It doesn't make sense to include a sum method on Stream, because it doesn't make sense to sum URLs, Classes, Threads, or any other non-numeric reference type.

在List上调用stream()将为您提供通用Stream,它可以处理任何引用类型,而不仅仅是数字类型。在Stream上包含sum方法没有意义,因为对URL,Classes,Threads或任何其他非数字引用类型求和没有意义。

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 ints, and calling sum() (or summaryStatistics(), which includes count, average, max, and min along with sum).

但这将涉及很多拆箱和拳击。通过将它转换为对int进行操作的IntStream,并调用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()

#2


3  

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. e.g. that could be Stream<Person>, Stream<Apple> etc. hence doesn't make sense to include a sum method.

因为Stream 是一种泛型类型,只要它涉及到它处理任何类型的对象。例如可能是Stream ,Stream 等因此包含sum方法没有意义。

#3


3  

Stream<Interger> and IntStream are actually different. As numbers.stream() returns an object of Type Stream and Stream interface does not have any method like sum. Another side numbers.stream().mapToInt(e -> e) returns IntStream which has the sum method.

Stream 和IntStream实际上是不同的。由于numbers.stream()返回Type Stream的对象,Stream接口没有像sum这样的方法。另一边是numbers.stream()。mapToInt(e - > e)返回具有sum方法的IntStream。

#4


2  

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>. 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>.

我的意思是在List接口上声明了stream(),它返回Stream 。你知道E实际上是一个整数,编译器必须推断它,并且它不像编译器在推断类型时可以改变返回类型,你仍然会得到一个通用的Stream

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. 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)

但是如果我更多地考虑它会更糟,在这种情况下,必须返回一个BaseStream,Stream 和IntStream都会扩展,而Stream 的总和没有意义。以后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,那么这确实是可能的,但在这种情况下会变得多么混乱。

#1


14  

Calling stream() on a List will get you a general-purpose Stream, which can handle any reference type, not just numeric types. It doesn't make sense to include a sum method on Stream, because it doesn't make sense to sum URLs, Classes, Threads, or any other non-numeric reference type.

在List上调用stream()将为您提供通用Stream,它可以处理任何引用类型,而不仅仅是数字类型。在Stream上包含sum方法没有意义,因为对URL,Classes,Threads或任何其他非数字引用类型求和没有意义。

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 ints, and calling sum() (or summaryStatistics(), which includes count, average, max, and min along with sum).

但这将涉及很多拆箱和拳击。通过将它转换为对int进行操作的IntStream,并调用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()

#2


3  

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. e.g. that could be Stream<Person>, Stream<Apple> etc. hence doesn't make sense to include a sum method.

因为Stream 是一种泛型类型,只要它涉及到它处理任何类型的对象。例如可能是Stream ,Stream 等因此包含sum方法没有意义。

#3


3  

Stream<Interger> and IntStream are actually different. As numbers.stream() returns an object of Type Stream and Stream interface does not have any method like sum. Another side numbers.stream().mapToInt(e -> e) returns IntStream which has the sum method.

Stream 和IntStream实际上是不同的。由于numbers.stream()返回Type Stream的对象,Stream接口没有像sum这样的方法。另一边是numbers.stream()。mapToInt(e - > e)返回具有sum方法的IntStream。

#4


2  

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>. 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>.

我的意思是在List接口上声明了stream(),它返回Stream 。你知道E实际上是一个整数,编译器必须推断它,并且它不像编译器在推断类型时可以改变返回类型,你仍然会得到一个通用的Stream

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. 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)

但是如果我更多地考虑它会更糟,在这种情况下,必须返回一个BaseStream,Stream 和IntStream都会扩展,而Stream 的总和没有意义。以后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,那么这确实是可能的,但在这种情况下会变得多么混乱。