繁体   English   中英

Java 8 Stream - 过滤和foreach方法不按预期打印

[英]Java 8 Stream - Filter and foreach method not printing as expected

我正在执行以下程序:

Stream.of("d2", "a2", "b1", "b3", "c")
.filter(s -> {
    System.out.println("filter: " + s);
    return true;
})
.forEach(s -> System.out.println("forEach: " + s));

我得到的输出是:

filter:  d2
forEach: d2
filter:  a2
forEach: a2
filter:  b1
forEach: b1
filter:  b3
forEach: b3
filter:  c
forEach: c

但是,我期待以下输出:

filter:  d2
filter:  a2
filter:  b1
filter:  b3
filter:  c 
forEach: d2
forEach: a2
forEach: b1
forEach: b3
forEach: c

意思是,首先应该完全执行filter方法循环,​​然后才能启动forEach方法循环。

有什么我做错了吗?

你的期望是错误的。

当执行终端操作forEach ,它一次消耗一个Stream元素。 每消耗元件具有传递的所有的中间操作Stream ,这会导致filter的元件上刚刚之前执行forEach被同一元件上执行(假设元件经过filter )。

换句话说,当Stream管道中的下一个操作需要其下一个元素时(在您的情况下,下一个操作是forEach ), filter被懒惰地应用于每个元素。

这意味着如果你的终端操作只需要处理一些Stream元素(例如,如果你用findFirst()替换了forEach() findFirst() ), filter()操作只会在第一个元素传递之前执行(在您的示例中,这意味着仅针对第一个元素执行过滤器)。

Stream的处理将从终端操作开始,并逐个使用一个项目。 优点是:

程序必须计算相关项目 - 例如,如果只需要一个项目,则只调用一次filter

Stream.of("d2", "a2", "b1", "b3", "c")
.filter(s -> {
    System.out.println("filter: " + s);
    return true;
})
.findAny()
.ifPresent(s -> System.out.println("forEach: " + s));

输出:

filter: d2
forEach: d2

您甚至可以创建infinte Streams(否则将无法实现):

IntStream.iterate(0, i -> i+1)
.filter(s -> {
    System.out.println("filter: " + s);
    return true;
})
.peek(i -> {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
    }
})
.forEach(s -> System.out.println("forEach: " + s));

输出:

filter: 0
forEach: 0
filter: 1
forEach: 1
... (up to infinity)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM