Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Why can't I sum them like: numbers.stream().sum();?

Instead I have to do this: 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.

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

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

Why can't I sum a Stream of Integers?

like image 392
Robert Niestroj Avatar asked Jul 16 '18 18:07

Robert Niestroj


People also ask

How do you find the sum of a stream of integers?

We can use mapToInt() to convert a stream integers into a IntStream . int sum = integers. stream(). mapToInt(Integer::intValue).

When should you not use Java 8 streams?

There are a few special cases where streams are hard to apply, like loop over 2 or 3 collections simultaneously. In such case streams make not much sense, for is preferable. But in general there are no rules when to use or not to use specific construct.

What is disadvantages of stream in Java 8?

Limitations Of Streams : Once a Stream is consumed, it can't be used later on. As you can see in above examples that every time I created a stream. Lambda expressions (as well as anonymous classes) in Java can only access to the final (or effectively final) variables of the enclosing scope.


4 Answers

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.

You could sum the elements by calling 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).

You could even use IntStream.of and avoid boxing the values even once.

IntStream.of(1, 2, 3).sum()
like image 154
rgettman Avatar answered Oct 13 '22 05:10

rgettman


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.

like image 31
Amit Bera Avatar answered Oct 13 '22 06:10

Amit Bera


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.

like image 42
Ousmane D. Avatar answered Oct 13 '22 05:10

Ousmane D.


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

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)

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.

like image 43
Eugene Avatar answered Oct 13 '22 04:10

Eugene