Summing a List of numbers in Java
Tags: java, beginners
Published: 2020-05-08 11:43:27

Every now and then I need to do some basic stuff in Java and I wonder: "what is the best way to this".  This happened to me a few days ago. I needed to do a simple thing as "get the sum of a List of numbers" and I found out there are a number of ways — pun intended — to do this.

## The old fashion approach

We can create a simple loop to do this. I am using Java 11 so forgive me if the `List.of` and `var` does not work in your case when you, for instance, use Java 8. However, you probably will still get the point.

```java
        var listOfNumbers = List.of(1,2,3,4,5,6,7,8,9,10);

        var sum = 0;
        for (int i = 0; i < listOfNumbers.size() ; i++) {
            sum += listOfNumbers.get(i);
        }
```

Obviously, since Java 5, we have enhanced for loops so I can rewrite the same code like this.

```java
        var listOfNumbers = List.of(1,2,3,4,5,6,7,8,9,10);

        var sum = 0;
        for (int number : listOfNumbers) {
            sum += number;
        }
```
The difference is subtle. However it is already more expressive as it says somehting like: "of each `number` comming from `listOfNumbers` I want to do the following ..." 

## The Java Stream approach

People who know me, know that I was brainwashed during my university days with programming [Haskell](https://en.wikipedia.org/wiki/Haskell_(programming_language)). This means I have a lot of love for pure functional programming. Not that Java can handle that 😉, but the expressiveness of functional programming is somewhat available using the stream API.

With the stream API in Java, we can execute the MapReduce programming model. For the issue I am trying to solve here, I do not need to map as the numbers will stay as they are. I do however have to reduce the List into a single number, the sum.

### Collect

In probably 99% of the cases, we probably use the collect function with the standard `toList()` collector to reduce our stream back into a List.
Similar to this:
```java
        var time2ToList = listOfNumbers.stream()
                .map(i -> i * 2)
                .collect(Collectors.toList());
```
However, there is more to life collecting a stream back into a List. Browsing to the Collectors library you will function like `summingInt()`, `summingDouble()` and `summingLong()`

You can use these functions to collect (or reduce) the List into the sum.
The summmingInt function does require a function that turns the input you have into an `int`. In this case, I can simply use the "[identity function](https://en.wikipedia.org/wiki/Identity_function)". The function `i -> i` will be sufficient.

```java
        var listOfNumbers = List.of(1,2,3,4,5,6,7,8,9,10);
        var sum = listOfNumbers.stream().collect(Collectors.summingInt(i -> i));
```
This identity function might look silly so can equally use Integer.intValue(). 

```java
        var listOfNumbers = List.of(1,2,3,4,5,6,7,8,9,10);
        var sum = listOfNumbers.stream()
                .collect(Collectors.summingInt(Integer::intValue));
```

When I do this, my IDE — IntelliJ IDEA in my case — advise me to refactor this and use the `mapToInt()` function like this.

```java
        var listOfNumbers = List.of(1,2,3,4,5,6,7,8,9,10);
        var sum = listOfNumbers.stream().mapToInt(Integer::intValue).sum();
```

Technically what we do here is mapping every item to an `int`, what it already is ¯\\_(ツ)_/¯ and reduce it with the sum() function.

It gets more clear if you look at the inferred types. You simply cannot have a List of primitives. So the List is a list of Integer (the Object). This means that every item in the list needs to get back to the primitive `int` to make the `sum()` possible. The previous example with the identity function in the collector works because of Java unboxing.

If you would like to use primitive Lists in Java, I would suggest taking a look at the [Eclipse Collections](https://www.eclipse.org/collections/) library.

### Reduce

Reduction in Java is achieved by a couple of function in the stream API
In addition to `collect()` there is also the obviously named function `reduce()`

```java
        var listOfNumbers = List.of(1,2,3,4,5,6,7,8,9,10);
        var sum = listOfNumbers.stream().reduce(0 , (num1, num2) -> num1 + num2);
```
The reduce function in this case takes a starting point and BIFunction lambda expression. The BiFunction will be applied to the starting point and the first number. The result of the function will be applied to the second number and so on. 
The code above does something like this.
0 + 1
1 + 2
3 + 3
6 + 4
etc ...

Now, you can omit the starting point `0`. However, the reduce function will return an Optional in this case as the List it tries to reduce might be empty.

## Conclusion

As you can see, there are multiple ways to solve this problem. Without any doubt, people will come up with even more exotic ways to solve this. My personal favorite is the `reduce()` option. For me, this is the most expressive and pure solution in Java. I simply only want to reduce a list to a single number and don't need to care of the transformations from boxed types to primitives. Furthermore, I can reuse this approach when I need to reduce a List of other types by writing a reduction lambda function that fits my needs.