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

References

  1. Supplier JavaDoc
  2. Stream summary JavaDoc

Leave a Reply

Your email address will not be published. Required fields are marked *