In Java 8, Stream cannot be reused, once it is consumed or used, the stream will be closed.
1. Example – Stream is closed!
Review the following example, it will throw an IllegalStateException
, saying “stream is closed”.
TestJava8.java
package com.favtuts.java8.stream; import java.util.Arrays; import java.util.stream.Stream; public class StreamClosedAfterOperated { public static void main(String[] args) { demoStreamIsClosed(); } static void demoStreamIsClosed() { String[] array = {"a", "b", "c", "d", "e"}; Stream<String> stream = Arrays.stream(array); // loop a stream stream.forEach(x -> System.out.println(x)); // reuse it to filter again! throws IllegalStateException long count = stream.filter(x -> "b".equals(x)).count(); System.out.println(count); } }
Output
a
b
c
d
e
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
at java.base/java.util.stream.AbstractPipeline.<init>(AbstractPipeline.java:203)
at java.base/java.util.stream.ReferencePipeline.<init>(ReferencePipeline.java:94)
at java.base/java.util.stream.ReferencePipeline$StatelessOp.<init>(ReferencePipeline.java:696)
at java.base/java.util.stream.ReferencePipeline$2.<init>(ReferencePipeline.java:165)
at java.base/java.util.stream.ReferencePipeline.filter(ReferencePipeline.java:164)
at com.favtuts.java8.stream.StreamClosedAfterOperated.demoStreamIsClosed(StreamClosedAfterOperated.java:20)
at com.favtuts.java8.stream.StreamClosedAfterOperated.main(StreamClosedAfterOperated.java:9)
2. Example – Reuse a stream
For whatever reason, you really want to reuse a Stream, try the following Supplier
solution :
TestJava8.java
package com.favtuts.java8.stream; import java.util.Arrays; import java.util.function.Supplier; import java.util.stream.Stream; public class StreamClosedAfterOperated { public static void main(String[] args) { useSupplierToReuseStream(); } static void useSupplierToReuseStream() { String[] array = {"a", "b", "c", "d", "e"}; Supplier<Stream<String>> streamSupplier = () -> Stream.of(array); //get new stream streamSupplier.get().forEach(x -> System.out.println(x)); //get another new stream long count = streamSupplier.get().filter(x -> "b".equals(x)).count(); System.out.println(count); } }
Output
a
b
c
d
e
1
Each get()
will return a new stream.
Why?
May I know why you need to reuse a stream, for testing?
Download Source Code
$ git clone https://github.com/favtuts/java-core-tutorials-examples
$ cd java-basic/java8/stream