takeWhile 与过滤器有何不同?

How is takeWhile different from filter?

takeWhile() 与 filter() 有何不同 Java 9. 它有什么额外的用途?

Stream.of(1,2,3,4,5,6,7,8,9,10).filter(i -> i < 4 )
        .forEach(System.out::println);

这也许就是下面会做的事情

Stream.of(1,2,3,4,5,6,7,8,9,10).takeWhile(i -> i < 4 )
        .forEach(System.out::println);

当时需要这个新功能是什么?

filter 将从流中删除所有不满足条件的项目。

takeWhile 将在第一次出现不满足条件的项目时中止流。

例如

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);

将打印

123321

但是

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);

将打印

123

根据此博客post: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.

我用粗体标记了重要内容。

来自 post 的示例:

Stream.of("a", "b", "c", "", "e")
    .takeWhile(s -> !String.isEmpty(s));
    .forEach(System.out::print);

输出abc。因为它会过滤直到第一个与谓词不匹配(在示例中为第 4 个元素)。所以你可以说它正在使流短路。

它可用于获取第一个 null 值的索引,例如

Stream.of("Test", "Test2", null, "Test2", null).takeWhile(Objects:isNull).count();

您可以对 filter 执行相同的操作,但在这种情况下,您需要有一个条件来在您获得第一个空值时立即中断过滤器。所以实际上 filter 不适合那种工作,而 takeWhile 恰好适合这种情况。

差异

takeWhile

过滤器为真时取值,然后停止

过滤器

获取所有匹配过滤器的值

例子

Stream.of(1,2,3,4,5,6,7,8,9,10).filter(i -> i % 2 == 0 )
    .forEach(System.out::println);

TIO

这将输出从 2 到 10 的所有偶数。

Stream.of(1,2,3,4,5,6,7,8,9,10).takeWhile(i -> i % 2 == 0 )
    .forEach(System.out::println);

TIO

这不输出任何东西,因为 1 不是偶数,所以它在输出任何东西之前停止。

操作 takeWhiledropWhile 比过滤器更有效,如果你知道源是 sorted。这些操作利用了短路,这意味着:计算会因为找到结果而停止,不需要使用过滤操作来处理整个流