Learning Java 8 - Streams

This is the second post on my personal journey to learn Java 8. With Learning Java 8 - Lambda Expressions we scratches the surface of Java 8 lambda expressions. The current post is to get a first impression of the new java.util.stream.Stream API.

There are various ways to create a Java 8 Stream.

Let's start with the creation of an empty stream (e.g. to return a meaningful default value instead of null):

import static java.util.stream.Stream.empty;

Stream<Object> emptyStream = empty();

One of the easiest way to generate a short Stream is to use the Stream.of method.

Which leads us directly to the famous Hello World of Stream:

import static java.util.stream.Stream.of;

Stream<String> helloWorld = of("Hello", "World");

Time to generate an endless constant stream foreverFortyTwo (from a Supplier you should know from part I):

import static java.util.stream.Stream.generate;
import static java.util.Boolean.true;

Supplier<Integer> fortyTwo = () -> 42;
Stream<Boolean> foreverFortyTwo = generate(fortyTwo);

To generate random numbers you can do it yourself (with a method reference):

Stream<Double> randomDoubles = generate(Math::random);

or choose one of the new method of Random to generate an IntStream with ints:

import java.util.stream.IntStream;
import static java.util.Random.ints;

IntStream randomInts = ints();

Speaking of new methods we continue with the Stream.iterate method to implement infinite sequential ordered Streams. We start with the natural numbers:

import static java.util.stream.Stream.iterate;

Stream<Integer> positiveIntegers = iterate(1, (seed) -> seed + 1);

positiveIntegers.limit(10).forEach(System.out::println);

Since our positiveIntegers represent an endless Stream we limit the stream during printing...

With a nice trick you can easily calculate more complex functions like the Fibonacci sequence):

import static java.util.stream.Stream.iterate;

Stream<Integer> fibonacciSequence = iterate(new int[]{0, 1}, seed -> new int[]{seed[1], seed[0] + seed[1]})
    .map(n -> n[0]);

We used an array to store the intermediate results of the Function n -> n[0]. Afterwards we use map to drop those intermediate values.

Last but not least: Reduction.

Best explained by looking at the specialized reduction forms of IntStream

function reduction equivalent
sum() reduce(0, Integer::sum)
min() reduce(Integer::min)
max() reduce(Integer::max)

With this in mind we tackle the factorial 10! in one line:

import static java.util.stream.IntStream.rangeClosed;

int factorialOfTen = rangeClosed(1, 10).reduce(1, (a, b) -> a * b);

Convert a Stream to an Array:

Planet[] myArray = planetStream.toArray(Planet[]::new);

There is a lot more to explore in the java.util.stream package, but that's a story for another day...