## Introduction

In this post, we will see three ways to sum a stream of numbers using Java streams. We will use a stream created from a list of integers and sum the integers using various approaches.

## Option 1 - Using mapToInt on the Stream

A stream can contain elements of any type, whereas an IntStream represents a sequence of primitive int-valued elements. We can convert a stream of arbitrary type to an IntStream by using the *mapToInt* method on the stream.

**mapToInt method signature:**

```
IntStream mapToInt(ToIntFunction<? super T> mapper);
```

The *mapToInt* method takes a ToIntFunction. A *ToIntFunction* is a functional interface which maps any element to a *primitive int* value. It has a single method called *applyAsInt* as shown below.

```
int applyAsInt(T value)
```

When we pass an instance of *ToIntFunction* to the *mapToInt* method, it applies this function to each element in the stream and returns an IntStream. An IntStream has a *sum()* method to sum all the elements in the IntStream (which are primitive integers).

```
List<Integer> integers = List.of(1, 2, 3, 4, 5);
int sum = integers.stream()
.mapToInt(Integer::intValue)
.sum();
```

Note: * List.of* method was added in Java 9 as part of the many Collection factory methods. If you are using Java 8 or lower, use

*Arrays.asList*instead.

In the above example, calling *stream()* on the collection returns a stream of integers (*Stream<Integer>*). *Integer::intValue* is a method reference for the lambda expression `element -> element.intValue()`

. It unboxes an Integer to a primitive int and thus it satisfies the *ToIntFunction* method signature (i.e., it takes an *Integer* object and returns a primitive int). Since we have an IntStream, we call the sum method on it to find the sum of elements in the (Int)Stream.

However, there is another way we could have written the *mapToInt* to make advantage of the automatic unboxing.

```
int sum = integers.stream()
.mapToInt(e -> e)
.sum();
```

The lambda expression `e -> e`

returns the same Integer instance. But, under the hood, automatic unboxing takes place and hence this is equivalent to calling the *intValue* method on the Integer object.

### Sum a Java Stream as a long or double

We can use the *mapToLong* and *mapToDouble* methods to map an element to a long and a double, respectively. It will return a LongStream and a DoubleStream, respectively. Then, calling *sum()* on the LongStream or DoubleStream will return a double or a long.

**Note:**

**mapToLong**takes a*ToLongFunction*. The*ToLongFunction*has a single method called*applyAsLong*to map an element to a*primitive long*.**mapToDouble**takes a*ToDoubleFunction*. The*ToDoubleFunction*has a single method called*applyAsDouble*to map an element to a*primitive double*.

```
long sumAsLong = integers.stream()
.mapToLong(Integer::intValue)
.sum();
double sumAsDouble = integers.stream()
.mapToDouble(Integer::intValue)
.sum();
```

## Option 2 - Sum a Java Stream by reducing the stream

The second way by which we can sum a stream of numbers is to use the *reduce* method on the stream. The reduce method performs a reduction on the stream elements using the provided

*identity**element*and- an
*accumulator function*

The identity element when passed to the accumulator function with some other element (say *e*) must return the other element (*e*) as the result.

Example: The identity element for addition is 0, because 0 + e (any element) gives us e. The identity for multiplication is 1 (1 x e = e).

The accumulator function is represented by a **BinaryOperator**. A BinaryOperator is a BiFunction i.e., it takes two elements of a type and returns a single result of the same type.

```
int sum = integers.stream()
.reduce(0, (a, b) -> a + b);
```

We pass an identity value of 0 for the accumulator function. The accumulator function takes two elements of type int and returns the sum of them (an int). Since the Integer’s *sum* method takes two integers and returns the sum of it, we can use a method reference in its place, as shown below.

```
int sum = integers.stream()
.reduce(0, Integer::sum);
```

I have a separate post on Java Stream reduce method where I talk in depth on the three overloaded **Stream#reduce** methods.

## Option 3 - Using Collectors.summingInt

The *Collectors.summingInt* is a Collector that sums the primitive integers. It accepts a *ToIntFunction* (the same type passed for the *mapToInt* method) to convert an element in the stream to a *primitive int.*

We can use the **Stream#collect** along with **Collectors.summingInt** as shown below.

```
int sum = integers.stream()
.collect(Collectors.summingInt(Integer::intValue));
```

However, this is a roundabout way of computing a stream’s sum. The Intellij IDE suggests to refactor the above to use *mapToInt* (the first method).

## Sum a stream obtained from a Map

So far, we have learnt three ways to sum a stream of numbers where the stream was created from a list. If we had a map, then we just have to create a stream of integers out of the map’s values or keys and use any of the methods we’ve seen.

Let us say we have the below map.

```
Map<Integer, String> map = Map.of(
1, "abc",
2, "defg",
3, "pqrs",
4, "uvw",
5, "xyz");
```

We want to find the *sum* of the lengths of all *even length* strings.

```
int result = map.values()
.stream()
.filter(string -> string.length() % 2 == 0)
.mapToInt(String::length)
.sum();
System.out.println(result); //8
```

We create a *Stream<String>* from the map values, filter the strings whose length is of even length. Then in the *mapToInt*, we map a string element into an integer, i.e., the length of the string. Finally, we call *sum()* on the stream to get the result.

## Conclusion

In this post, we learnt three ways to sum a stream of integers in Java. We looked at the *mapToInt*, *reduce*, and *collect methods* from the Stream.

## References

- Baeldung Stream Sum
- How to sum a list of integers with java streams - Stackoverflow post