Learn new Java 9 improvements in Stream API i.e. takeWhile
/ dropWhile
methods, ofNullable
and iterate
methods with examples.
1. Limiting a Stream with takeWhile() and dropWhile()
The new methods takeWhile and dropWhile allow us to get portions of a stream based on a predicate.
- The takeWhile() returns a stream consisting of the elements from the stream while a specified predicate remains true.
- The dropWhile() returns a stream consisting of the elements from the stream after a specified predicate remains false.
1.1. takeWhile() Example
In this example, takeWhile(n -> n < 5)
creates a stream containing only the elements from the original stream as long as the value is less than 5.
Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
Stream<Integer> lessThanFive = numbers.takeWhile(n -> n < 5);
lessThanFive.forEach(System.out::println); // Output: 1 2 3 4
The program output:
1 2 3 4
1.2. dropWhile() Example
As stated before, the dropWhile acts opposite to the takeWhile method, so in the above example, if used, dropWhile(n -> n < 5)
creates a stream containing the elements from the original stream, starting from the first element that is not less than 5.
Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
Stream<Integer> greaterThanFive = numbers.dropWhile(n -> n < 5);
greaterThanFive.forEach(System.out::println); // Output: 5 6 7 8 9
The program output:
5 6 7 8 9
2. Stream iterate() with Predicate
The iterate() methods are used to create a stream that starts with a single element (the seed), and subsequent elements are produced by successively applying the unary operator.
- The result is an infinite stream.
- To terminate the stream, a limit or some other short-circuiting function, like
findFirst
orfindAny
is used.
The iterate method in Java 8 has the signature:
static Stream iterate(final T seed, final UnaryOperator f)
In Java 9, a new overloaded version of iterate takes a Predicate as the second argument:
static Stream iterate(T seed, Predicate<? super T> hasNext, UnaryOperator next)
Let’s see the difference in the use of the iterate method from Java 8 to Java 9.
2.1. iterate() in Java 8
This example generates the first 10 numbers of the Fibonacci sequence using iterate and limit methods.
Stream<Integer> fibonacci = Stream.iterate(new int[]{0, 1},
t -> new int[]{t[1], t[0] + t[1]})
.limit(10) // Limit to avoid infinite stream
.map(t -> t[0]);
fibonacci.forEach(System.out::println);
The program output:
0 1 1 2 3 5 8 13 21 34
2.2. iterate() in Java 9
This example generates the first 10 numbers of the Fibonacci sequence using iterate and Predicate condition.
Stream<Integer> fibonacci = Stream.iterate(0,
n -> n < 10,
n -> {
int next = n + (n > 0 ? n - 1 : 0);
return next;
});
fibonacci.forEach(System.out::println);
The program output:
0 1 1 2 3 5 8 13 21 34
In above examples, the first stream is the Java 8 way of using iterate with a limit. The second one uses a Predicate as the second argument.
3. Stream ofNullable()
Until Java 8, we cannot have null value in a stream. It would have caused NullPointerException.
In Java 9, the ofNullable method creates a stream containing the given nullable value if it is not null. Otherwise, creates an empty stream.
Stream<String> stream = Stream.ofNullable("123");
System.out.println(stream.count()); // 1
stream = Stream.ofNullable(null);
System.out.println(stream.count()); // 0
Here, the count
method returns the number of non-empty elements in a stream.
Technically, Stream.ofNullable() is very similar to a null condition check in the context of stream API.
Drop me your questions in the comments section.
Happy Learning !!
Comments