New features in Java 9 Stream API

Dilan Tharaka
3 min readJun 26, 2020

--

Photo by ArtHouse Studio from Pexels
Photo by ArtHouse Studio from Pexels

Java Stream API introduced in Java 8 was a game-changer and almost every Java developer love using Streams. Since Java 8, the Stream API is improving in each Java release. In this article, I’m talking about the new features added to the Java Stream API in Java version 9.

iterate

Java 8 had this iterate method. In that method, we can give a seed value ( a starting value) and a function to generate the next value given the current value for the stream. But there was no way to give a termination condition for the stream.

Stream.iterate(0, i -> i + 1)
.forEach(System.out::println);

The above stream can be used as a replacement for a for loop like following,

for (int i = 0; ; i++) {
System.out.println(i);
}

And in the loop, we can specify a termination condition like this,

for (int i = 0; i < 10; i++) {
System.out.println(i);
}

But in Java 8 Stream iterate method there’s no way to give a terminating condition. To replace the above loop in Java 8 Stream, we have to use a hack like following,

Stream.iterate(0, i -> i + 1)
.peek(System.out::println)
.allMatch(i -> i < 9);

In Java 9, there’s an overload iterate method which takes a function to give terminating condition. Using the new iterate method, we can obtain the same functionality conveniently like following,

Stream.iterate(0, i -> i < 10, i -> i + 1)
.forEach(System.out::println);

Using the new iterate method, we can replace a for loop easily in Java Stream.

takeWhile

takeWhile acts like the break statement in a loop. Let’s consider the following for loop,

int[] numbers = new int[]{1, 2, 10, 3, 7, 345, 55};
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] > 5) {
break;
}
System.out.println(numbers[i]);
}
// Output
// 1
// 2

This loop uses a condition and a break statement to break the loop when it meets an element that is greater than 5. Achieving this in Java 8 Stream is not an easy task ( this is not filtering. If filter, then number 3 would also be in the output). But in Java 9 we can use takeWhile to get the same result.

int[] numbers = new int[]{1, 2, 10, 3, 7, 345, 55};
IntStream.of(numbers)
.takeWhile(i -> i < 5)
.forEach(System.out::println);

As you can see takeWhile acts the same as the break statement. It continues until the given logic is true and when it gets the first element where the result is false, then the stream ends there.

dropWhile

dropWhile is somewhat similar to the takeWhile, but the difference is it drops the elements in the stream until the given statement is true, after that it provides all the other elements. See the following code to understand how it works,

int[] numbers = new int[]{1, 2, 10, 3, 7, 345, 55};
IntStream.of(numbers)
.dropWhile(i -> i < 5)
.forEach(System.out::println);
// Output
// 10
// 3
// 7
// 345
// 55

In this code, dropWhile drops the first two elements since they are less than five, but the third element (10) is greater than 5. Therefore after the third element, it gives all the elements in the stream.

ofNullable

The ofNullable method in Java 9 Stream API returns a Stream of a single element if the element is not null. Following is a simple usage of the ofNullable,

String value = null;
Stream.ofNullable(value)
.forEach(System.out::println);

This code would print nothing since the value is null. If we go to a more useful scenario of ofNullable consider following,

Stream.of(1, 2, null, 4, 5)
.flatMap(Stream::ofNullable)
.forEach(System.out::println);

In the above code, it avoids null values from the stream.

Those are the new features that came with Java 9 release to the Steam API. Using those features, we can replace almost every loop in Java codes effortlessly. If you have any interesting use case of them, don’t hesitate to leave a comment. Happy Coding 💻

--

--

Dilan Tharaka
Dilan Tharaka

Written by Dilan Tharaka

Software engineer curious about how things actually work

No responses yet