One of the most useful methods that was added to the Stream class, starting with JDK 9, was takeWhile​(Predicate<? super T> predicate). This method comes with two different behaviors, as follows:
- If the stream is ordered, it returns a stream consisting of the longest prefix of elements taken from this stream that match the given predicate.
- If the stream is unordered, and some (but not all) of the elements of this stream match the given predicate, then the behavior of this operation is nondeterministic; it is free to take any subset of matching elements (which includes the empty set).
In the case of an ordered Stream, the longest prefix of elements is a contiguous sequence of elements of the stream that match with the given predicate.
For example, fetching a list of 10 integers can be done as follows:
List<Integer> result = IntStream
.iterate(1, i -> i + 1)
.takeWhile(i -> i <= 10)
.boxed()
.collect(Collectors.toList());
This will give us the following output:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
Alternatively, we could fetch a List of random even integers until the first generated value is less than 50:
List<Integer> result = new Random().ints(1, 100)
.filter(i -> i % 2 == 0)
.takeWhile(i -> i >= 50)
.boxed()
.collect(Collectors.toList());
We can even join the predicates in takeWhile():
List<Integer> result = new Random().ints(1, 100)
.takeWhile(i -> i % 2 == 0 && i >= 50)
.boxed()
.collect(Collectors.toList());
One possible output can be obtained as follows (it can be empty as well):
64, 76, 54, 68
How about fetching a List of random passwords until the first generated password doesn't contain the ! character?
Well, based on the helper we listed earlier, we can do this like so:
List<String> result = Stream.generate(Main::randomPassword)
.takeWhile(s -> s.contains("!"))
.collect(Collectors.toList());
One possible output can be obtained as follows (it can be empty as well):
0!dac!3c, 2!$!b2ac, 1d12ba1!
Now, let's assume that we have an unordered stream of integers. The following snippet of code takes a subset of elements that are less than or equal to 10:
Set<Integer> setOfInts = new HashSet<>(
Arrays.asList(1, 4, 3, 52, 9, 40, 5, 2, 31, 8));
List<Integer> result = setOfInts.stream()
.takeWhile(i -> i<= 10)
.collect(Collectors.toList());
One possible output is as follows (remember that, for an unordered stream, the result is nondeterministic):
1, 3, 4