Java 9: Get more power with Java 9 Stream API Enhancements

Reading Time: 3 minutes

We discussed the Optional API enhancements in my previous blog. In this blog, we will discuss the Stream API enhancements in Java 9.

Stream API was introduced in Java 8 which gives us the power of using the collections in a declarative manner. We use the high order functions in the Stream APIs.

In Java 9, they have introduced some more features:

  • dropWhile()
  • takeWhile()
  • iterate()
  • ofNullable()

We will discuss all the above 4 methods one by one with code examples, so let’s start.

dropWhile():

This method drops all the elements from the stream till the predicate returns true.

dropWhile() method takes the Predicate as an argument which returns true or false, so till the time predicate is true, this method will drop the elements from the stream and as predicate gets failed, it will stop dropping the element and returns the stream with remaining elements.

Let’s understand this with a simple example:

Stream<Integer> myStream = Stream.of(2, 5, 8, 10, 15, 25, 30);
myStream.dropWhile(num -> num < 20).forEach(num -> System.out.println(num));

The output will be:

25
30

You can see, it dropped all the elements which are less than 20 and return the stream with the remaining elements.

But one interesting thing to note here that the output will be different if we make the above stream unordered.

The dropWhile() method drops all the elements until the given predicate fails, this method does not check further elements of the stream once the predicate fails. So in the case of an unordered stream, the resultant stream can still contain the elements which match the predicate.

Let’s understand this with the below example:

Stream<Integer> myStream = Stream.of(2, 5, 8, 25, 10, 15, 30);
myStream.dropWhile(num -> num < 20).forEach(num -> System.out.println(num));

The output will be:

25
10
15
30

In the above output you can see, it still contains the elements which are < 20 but as the stream is unordered and once the predicate failed at element 25, it did not check further and returned the output.

takeWhile():

This method is just opposite to the dropWhile() method. It takes all the elements from the stream till the predicate returns true.

takeWhile() method takes the Predicate as an argument which returns true or false, so till the time predicate is true, this method will take the elements from the stream and as predicate gets failed, it will stop taking the elements further and returns the stream.

Let’s try to understand this with the example:

Stream<Integer> myStream = Stream.of(5, 10, 15, 30, 40, 50);
myStream.takeWhile(num -> num < 20).forEach(num -> System.out.println(num));

The output will be:

5
10
15

You can see, it took only the elements which are less than 20. It dropped all the elements after that.

But the unordered stream behavior applies with takeWhile() method as well.

takeWhile() method also does not check further elements once the Predicate gets failed. So if the stream is unordered then the resultant stream can contain the elements which match the predicate.

Let’s look at the below example:

Stream<Integer> myStream = Stream.of(5, 10, 30, 15, 40, 50);
myStream.takeWhile(num -> num < 20).forEach(num -> System.out.println(num));

The output will be:

5
10

You can see that the element 15 was dropped because it came after 30 where Predicate got failed and the resultant stream contains only 5, 10.

iterate():

The iterate() method takes 3 arguments.
First argument is the initialising value from where the stream starts.
Second argument is the predicate, the iteration continues till this given predicate returns true. Once the predicate returns false, iteration gets stopped and the resultant stream gets returned
Third argument updates the value of previous iteration.

Let’s take an example:

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

The output will be :

0
1
2
3
4
5
6
7
8
9

In the above example,

  • the 1st aruguments says that stream starts from 0.
  • the 2nd argument which is a predicate i -> i < 10 returns true untill the values is 9, and
  • the 3rd argument increases the previous iteration value by 1.

We can relate the iterate() method with the normal for loop:

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

ofNullable():

This method is useful to avoid NullPointerException. This method returns an empty stream if the stream is null else returns the non empty stream.

We can relate this with the Optional API. Optional also have ofNullable() method which returns empty if the value inside the method is null.

Let’s understand this with the example:

Stream<String> stream = Stream.ofNullable(null);
stream.forEach(str -> System.out.println(str));

The output will be the empty. It will not print anything as the resultant stream is empty.

Now, let’s take an exmpale of non empty stream.

Stream<String> stream = Stream.ofNullable("rishi");
stream.forEach(str -> System.out.println(str));

This time the output will be non empty.

rishi

That’s it for this blog. I hope, this blog will help you to understand the Java 9 Stream API enhancements and you will be able to use it more efficiently in the code.

blog-footer

Written by 

Rishi is a Lead Consultant, with experience of more than 7 years. Rishi is product focused developer who loves developing both front-end user interfaces and scalable back-end infrastructure. He is a good team player, quick learner and a humble person. He has good time management skills, aimed to give best results and fully dedicated towards his work & responsibilities. He is able to work as individual and as well as in team. He loves to share his knowledge, therefore he often writes technical blogs.