
java.lang.IllegalStateException: stream has already been operated upon or closed
In Java 8 a Stream object cannot be reused after it has been reused or worked upon.After any Stream operation, that particular Stream will be closed automatically.
See the Example below:
import java.util.Arrays;
import java.util.stream.Stream;
public class StreamTestingClass {
public static void main(String[] args) {
String[] array = new String[]{"a", "b","c","d"};
Stream dataStream = Arrays.stream(array);
//Using the dataStream 1st time
dataStream.forEach(System.out::println);
//Using the dataStream for the 2nd time.. GIVES EXCEPTION!!
dataStream.forEach(System.out::println);
}
}
This will give the following Exception:
a
b
c
d
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
at java.util.stream.AbstractPipeline.sourceStageSpliterator(AbstractPipeline.java:279)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at codermag.net.java8.StreamTestingClass.main(StreamTestingClass.java:15)

This proves that the command executes for the 1st time.
For the 2nd time it fails.
SOLUTION: Use java.util.function.Supplier Class
To reuse a Stream we need to use java.util.function.Supplier.java.util.function.Supplier allows you to get multiple instance of the same Stream.
import java.util.Arrays;
import java.util.function.Supplier;
import java.util.stream.Stream;
public class StreamTestingClass {
public static void main(String[] args) {
String[] array = new String[]{"a", "b","c","d"};
Supplier<Stream<String>> streamSupplier = () -> Arrays.stream(array);
//get a copy of the stream
streamSupplier.get().forEach(System.out::println);
//get another copy of the stream
streamSupplier.get().forEach(System.out::println);
}
}
The get() operation of java.util.function.Supplier.get() is used to get a new instance of the Stream.
This will help you to work on the Stream multiple times. Just call the get() as many times as required.