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.