为什么这个java Stream会运行两次?

Ili*_*kis 22 java java-8 java-stream

Java的API 8说:

在执行管道的终端操作之前,不会开始遍历管道源.

那么为什么以下代码抛出:

java.lang.IllegalStateException:stream已经被操作或关闭

Stream<Integer> stream = Stream.of(1,2,3);
stream.filter( x-> x>1 );
stream.filter( x-> x>2 ).forEach(System.out::print);
Run Code Online (Sandbox Code Playgroud)

根据API的第一个过滤操作不应该在Stream上操作.

Tun*_*aki 27

发生这种情况是因为您忽略了返回值filter.

Stream<Integer> stream = Stream.of(1,2,3);
stream.filter( x-> x>1 ); // <-- ignoring the return value here
stream.filter( x-> x>2 ).forEach(System.out::print);
Run Code Online (Sandbox Code Playgroud)

Stream.filter返回一个新的, Stream包含与给定谓词匹配的此流的元素.但重要的是要注意它是一个新流.当过滤器加入过滤器时,旧的操作已经进行.但新的不是.

引自StreamJavadoc:

应该仅对一个流进行操作(调用中间或终端流操作).

在这种情况下,filter是在旧Stream实例上运行的中间操作.

所以这段代码可以正常工作:

Stream<Integer> stream = Stream.of(1,2,3);
stream = stream.filter( x-> x>1 ); // <-- NOT ignoring the return value here
stream.filter( x-> x>2 ).forEach(System.out::print);
Run Code Online (Sandbox Code Playgroud)

正如Brian Goetz所说,你通常将这些调用链接在一起:

Stream.of(1,2,3).filter( x-> x>1 )
                .filter( x-> x>2 )
                .forEach(System.out::print);
Run Code Online (Sandbox Code Playgroud)