## Java Streams

Saurabh Sharma

Stream is an new abstraction that lets one process data in a declarative way.

The easiest way to learn a new API or a construct is by trying it. So here is an exercise that I tried to learn the Stream API. This is an exercise from exercism.io.

The problem is the famous `grains `problem doubling the number of grains on each square of the chess which has 64 squares (8×8).

I started of by keeping things simple having a `LinkedHashMap` that stores `pre-initalized` square and number of `grains`.

``private Map<Integer, BigInteger> lHM = new LinkedHashMap<>();``
``````private void Initialize() {
for(int i=0; i<64; i++) {
if (i == 0) {
lHM.put(Integer.valueOf(1), BigInteger.ONE);
continue;
}
lHM.put(i+1, lHM.get(i).multiply(BigInteger.TWO));
}
}``````

`lHM` defined is initalized for all the possible grain permutations for a 64 square board.

``lHM.put(i+1, lHM.get(i).multiply(BigInteger.TWO));``

E.g.

• For every square > 1 we are putting `Grains in the previous square * 2`

This is very simple version of and had to be improved so time to use Streams.

``````import java.math.BigInteger;
import java.util.Map;

import java.util.stream.IntStream;

/**
* Grains on a board.
* 1 + 2 + 6 + 18 + .......
*/
class Grains {

BigInteger grainsOnSquare(final int square) {
if (square < 1 || square > 64) {
throw new IllegalArgumentException("square must be between 1 and 64");
}
return BigInteger.TWO.pow(square - 1);
}

BigInteger grainsOnBoard() {
return IntStream.range(1, 65).mapToObj( i -> grainsOnSquare(i)).reduce(BigInteger::add).get();
}

}``````

I did away with the data-structure and resorted to use simple Streams – `IntStream`.

For the method

``grainsOnSquare``

I have used `pow` method of BigInteger which simple calculates 2^(Square – 1)

• 1st Square 2^0 = 1
• 2nd Square 2^1 = 2
• …. 4th Square 2^3 = 8

Now it is easier to read and optimised. How about the total grains here is where the streams come in handy for me as I do not have a DS storing any values.

``IntStream.range(1, 65).mapToObj( i -> grainsOnSquare(i)).reduce(BigInteger::add).get();``

I used the `range()` method to iterate between 1-64 as the second parameter is exclusive, and then for each square `i` I got the `grainsOnSquare` which was reduced using `BigInteger.add` and the final value is returned.

## References

• https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
• https://www.oracle.com/technical-resources/articles/java/ma14-java-se-8-streams.html
• https://docs.oracle.com/javase/tutorial/collections/intro/index.html