Java8: 4 facts about the new Stream API

Java8: 4 facts about the new Stream API
Photo by orbtal media / Unsplash

The long awaited lambda support lands in Java 8, which should be released this month (March 2014). Lambdas enable us to use some handy functional constructs. Most notably should be the changes to the Collection API.

Java 8 comes with a new "Stream" class which provides methods to work with collections in a more functional and therefor concise way. Every type of collection can be viewed as a Stream which can be built via a method "stream()".

Here is a small example with converts a stream of Strings to its lower cased version:

List<String> list = ...;
Stream<String> stream = list.stream();
Stream<String> lowerCase = stream.map(s -> s.toLowerCase());

What should you know about Streams?

1. Streams are lazy evaluated

When you call methods like "map" or "filter" that return a new Stream, the provided function will not be applied immediately to all elements in the stream. The function will only applied for requested elements.

Here is a concrete example:

Stream<String> aStream = stream.map(s -> s.toLowerCase()).filter(s -> s.startsWith("a"));

This line of code builds a new stream "aStream" from the "stream" and transforms each element to lower case and filters all elements starting with an "a". The "toLowerCase()"- and "startsWith"-Lambdas only get called when needed; means, when we start to iterate over the "aStream".

2. You can build infinitive streams

For example a stream of all natural numbers (until a Integer overflow):

Stream<Integer> naturalNumbers = Stream.iterate(1, e -> e + 1);

You can iterate over the this stream until 231-1 (=Integer.MAX_VALUE).

3. Streams can be reduced to a single value

Use the reduce function with an initial value and a function which computes the result of the current reduced value and the value of the current stream element.

For example, a reduction of an integer stream by multiplying each element with its ancestor:

naturalNumbers.limit(10).reduce(1, (x, y) -> x * y));

"x" is the current reduced value and "y" the value of a stream element.

Since "reduce" iterates over the whole stream the line above limits the stream of natural numbers to the first 10 numbers.

4. Streams can be evaluated in parallel

The Stream class provides a method "parallel()" which returns a parallel version of the stream. A parallel stream is internally divided into multiple substreams, which will be processed in parallel. At the end it returns the combined result of the parallel computation. This all is completely transparent to the stream's consumer.

However, make sure that your lambdas are side-effect free in the computation.

The following code calculates the average of all even natural numbers lower than a million in parallel:

double average = naturalNumbers
    .limit(1000000)
    .parallel()
    .filter(x -> x % 2 == 0)
    .average()
    .getAsDouble();

Java 8 Streams are a cool and useful new feature of the Java language and brings some (looong awaited) freshness to Java.