[英]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.