Java 9 Stream takeWhile and dropWhile
- schick09
- Aug 27, 2024
- 3 min read
Java 9 made some interesting additions to the Stream API - takeWhile and dropWhile. Before we go into the details of both, let's take a second to understand the difference between ordered streams and unordered streams.
There are two types of collections in Java. Ordered collections store elements in the order they are inserted (they maintain the insertion order). Unordered collections do not maintain any order (e.g., Map and Set).
takeWhile is similar to filter. It applies a predicate to the elements in a Stream and returns a new Stream with only the elements that match that predicate. However in an ordered stream, takeWhile only takes elements from the input Stream as long as the predicate is true. As soon as the predicate match is false, it throws away the remainder of the Stream.
For example:
List<String> names = List.of("Dave", "Deanna", "Douglas", "Ruby", "Violet");
.takeWhile(name -> name.charAt(0) == 'D')
.forEach(System.out::println);
This will print:
Dave
Deanna
Douglas
This works differently for unordered streams (Map, Set, etc). If some of the elements in the Stream match the predicate (but not all), you'll get a different result every time. That's not great. Here's an example:
/**
* Unordered Stream Example
*/
Set<String> names1 = Set.of("Dave", "Deanna", "Douglas", "Ruby", "Violet");
.takeWhile(name -> name.charAt(0) == 'D')
.forEach(System.out::println);
This will print a different result every time. Sometimes it will return an empty stream. Sometimes just "Dave". Sometimes just "Dave" and "Deanna", etc.
If all of the elements match the predicate, then it will just return the original Stream. For example:
/**
* Unordered Stream Example - all elements match the predicate
*/
Set<String> names1 = Set.of("Dave", "Deanna", "Douglas", "Dansby", "Deborah");
.takeWhile(name -> name.charAt(0) == 'D')
.forEach(System.out::println);
This will print:
Dave
Deanna
Douglas
Dansby
Deborah
The dropWhile operation is basically the opposite of takeWhile. It will remove elements while the given predicate for an element returns true and stop removing elements the first time the predicate returns false.
For ordered streams, dropWhile will remove the longest contiguous sequence of elements that match the predicate. The stream returned contains all elements in the stream that come after the first element that returned false from the predicate match.
For example:
/**
* Ordered Stream Example
*/
List<String> names = List.of("Dave", "Deanna", "Douglas", "Ruby", "Violet");
.dropWhile(name -> name.charAt(0) == 'D')
.forEach(System.out::println);
/**
* This will print: Ruby
* Violet
*/
/**
* UnOrdered Stream Example
*/
Set<String> names1 = Set.of("Dave", "Deanna", "Douglas", "Ruby", "Violet");
.dropWhile(name -> name.charAt(0) == 'D')
.forEach(System.out::println);
/**
* This will print a different result every time.
* Sometimes it will return an empty stream. Sometimes just "Dave"
* Sometimes just "Dave" and "Deanna", etc.
*/
Here's a link to our GitHub location to access an example of using the takeWhile and dropWhile Stream operations described above: https://github.com/daveschickconsulting/java_9_examples/tree/main/src/funwithstreamimprovements

Comments