How is takeWhile different from filter?
According to this blogpost: https://blog.codefx.org/java/java-9-stream/
Called on an ordered stream it will return a new one that consists of those element that passed the predicate until the first one failed. It’s a little like filter but it cuts the stream off as soon as the first element fails the predicate. In its parlance, it takes elements from the stream while the predicate holds and stops as soon as it no longer does.
i marked the important stuff in bold.
The example from the post:
Stream.of("a", "b", "c", "", "e")
.takeWhile(s -> !String.isEmpty(s));
.forEach(System.out::print);
Outputs abc
. Because it filters until the first one doesn't match the predicate (in the example the 4th element). So you could say it's shortcircuiting the stream.
The difference
takeWhile
Takes values while the filter is true, then stops
filter
Takes all the values that match the filter
Example
Stream.of(1,2,3,4,5,6,7,8,9,10).filter(i -> i % 2 == 0 )
.forEach(System.out::println);
TIO
This outputs all of the even numbers from 2 to 10 inclusive.
Stream.of(1,2,3,4,5,6,7,8,9,10).takeWhile(i -> i % 2 == 0 )
.forEach(System.out::println);
TIO
This outputs nothing, as 1 is not even, so it stops before outputing anything.
filter
will remove all items from the stream that do not satisfy the condition.
takeWhile
will abort the stream on the first occurrence of an item which does not satisfy the condition.
e.g.
Stream.of(1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1)
.filter(i -> i < 4 )
.forEach(System.out::print);
will print
123321
but
Stream.of(1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1)
.takeWhile(i -> i < 4 )
.forEach(System.out::print);
will print
123
It could be used to get the index of the first null
value e.g.
Stream.of("Test", "Test2", null, "Test2", null).takeWhile(Objects:isNull).count();
You could do the same with filter
but in that case you would need to have a condition to break the filter as soon as you get the first null value. So in practice filter
is not suited for that kind of work while takeWhile
is exactly for that case.