I'm learning the new Java 8 features, and while experimenting with streams (java.util.stream.Stream
) and collectors, I realized that a stream can't be used twice.
Is there any way to reuse it?
Java 8 streams cannot be reused. As soon as you call any terminal operation the stream is closed: Calling noneMatch after anyMatch on the same stream results in Exeption. Each call to get() constructs a new stream on which we are save to call the desired terminal operation.
So it is very important to remember that Java 8 streams can't be reused.
A Stream should be operated on (invoking an intermediate or terminal stream operation) only once. A Stream implementation may throw IllegalStateException if it detects that the Stream is being reused. Whenever a terminal operation is called on a Stream object, the instance gets consumed and closed.
Remember that loops use an imperative style and Streams a declarative style, so Streams are likely to be much easier to maintain. If you have a small list, loops perform better. If you have a huge list, a parallel stream will perform better.
While most intermediate operations will maintain the order of the Stream, some will, by their nature, change it. unordered and empty are two more examples of intermediate operations that will ultimately change the ordering of a Stream.
stream(). filter(i -> i >= 3); does not change original list. All stream operations are non-interfering (none of them modify the data source), as long as the parameters that you give to them are non-interfering too.
From the documentation:
A stream should be operated on (invoking an intermediate or terminal stream operation) only once.
A stream implementation may throw IllegalStateException if it detects that the stream is being reused.
So the answer is no, streams are not meant to be reused.
If you want to have the effect of reusing a stream, you might wrap the stream expression in a Supplier and call myStreamSupplier.get()
whenever you want a fresh one. For example:
Supplier<Stream<String>> sup = () -> someList.stream(); List<String> nonEmptyStrings = sup.get().filter(s -> !s.isEmpty()).collect(Collectors.toList()); Set<String> uniqueStrings = sup.get().collect(Collectors.toSet());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With