Java Programming Tutorials

Java programming tutorials with many code examples!

Create Java Streams

There are many ways to create Java Streams and for each of them we’ll show examples. This flexibility is needed especially when combined with flatMap!

Collection/Set/List/Map to Stream

In Java 8 many interfaces have been extended with default and static methods. Collections are not different. All of them have stream() method that allows us define stream of operations on elements of a collection. Here are a few examples:

Collection<String> names = asList("foo", "bar");
Stream<String> namesStream = names.stream();

Set<String> abc = new HashSet<>(asList("a", "b", "c"));
Stream<String> idStream = abc.stream();

List<Integer> fibos = asList(1, 1, 2, 3, 5);
Stream<Integer> fiboStream = fibos.stream();

// map -> stream of entries
Map<Integer,String> usersById = new HashMap<>();
Stream<Entry<Integer, String>> userStream
        = usersById.entrySet().stream();

Empty stream

Stream.empty() is convenient method that allows us to implement Null Object Pattern and always return a Stream, even if we have no data:

public <T> Stream<T> emptyStream(Collection<T> coll) {
    return coll != null ? coll.stream() : Stream.empty();
}

Stream of objects

To create a Stream of individual elements we can use Stream.of(T… values), which will turn given objects into a stream:

Stream<Object> items = Stream.of(new Object(), 2, "foo");

It’s sometimes useful when you have to return a stream for further stream processing, but have one or more objects – for example we could take them from a DTO.

Array to Stream

There are two ways to turn array into Stream. The first one is to use one of java.util.Arrays.stream(…) methods. They work great even with arrays of primitive types:

Integer[] nums = {1, 2, 3};
Arrays.stream(nums).forEach(System.out::print);

The other way is to use Stream.of(T… values). It works fine with arrays of objects:

Integer[] nums = {1, 2, 3};
Stream.of(nums).forEach(System.out::print);

In both cases the output will be 123.

But there is one gotcha when using Stream.of() version… If we pass an array of primitives it will create one element stream, where the only element will be the array of primitives! The correct way of transforming array of primitive types is to use Arrays.stream(…). Consider this:

int[] nums = {1, 2, 3};
System.out.print("Stream.of(nums): ");
Stream.of(nums).forEach(System.out::println);

System.out.print("Arrays.stream(nums): ");
Arrays.stream(nums).forEach(System.out::print);
System.out.println();

The output will be:

Stream.of(nums): [I@5b480cf9
Arrays.stream(nums): 123

String of chars

Having a String we can create a Stream of chars:

String transformed = "Hello".codePoints()
        .filter(c -> c > 90)
        .collect(StringBuilder::new,
                StringBuilder::appendCodePoint,
                StringBuilder::append)
        .toString();
System.out.println(transformed);

The codePoints() returns IntStream. Unfortunately, there is no specialized CharStream, that would allow us to conveniently operate on characters and, what’s more important, to turn the stream of characters back into a String. That’s why we use this funky collector.

The output of the above transformation is:

ello

Stream builder

The simplest way to build a stream, but IMHO less often used, is the StreamBuilder returned from Stream.builder() method. The following example clearly explains how to use it:

Stream<String> built = Stream.<String>builder()
        .add("x")
        .add("y")
        .add("z")
        .build();

built.forEach(System.out::print);
System.out.println();

In practice it’s very similar to Stream.of(T…). Anyways, the code prints:

xyz

Generate stream of values

Stream.generate(Supplier<T>) is a helper method that can be used to provide stream values from one source. It could be a file, database, or a simple lambda expression that will return always the same value. For example we can use Stream.generate() to implement function constantly that returns indefinitely the same value:

Stream<Integer> constantly = Stream.generate(() -> 1);
constantly.limit(10).forEach(System.out::print);
System.out.println();

As expected, the code will print 10 times 1:

1111111111

Stream of transformations

Stream.iterate(T seed, UnaryOperator<T> f) takes an initial value (seed) and returns it as the first value of the stream. Then, to produce further values, it executes provided function with the previous value as a parameter. Here’s an example of how to use Stream.iterate() to create a stream of even numbers:

Stream<Integer> evenNumbers = Stream.iterate(0, p -> p + 2);
evenNumbers.limit(5).forEach(System.out::print);
System.out.println();

The code prints:

02468
Share with the World!