Java - ストリームは既に操作されているか、閉じています

Java –ストリームはすでに操作されているか閉じられています

Java 8では、Streamは再利用できません。消費または使用されると、ストリームは閉じられます。

1. 例–ストリームは閉じられています!

次の例を確認してください。「ストリームが閉じています」というIllegalStateExceptionがスローされます。

TestJava8.java

package com.example.java8;

import java.util.Arrays;
import java.util.stream.Stream;

public class TestJava8 {

    public static void main(String[] args) {

        String[] array = {"a", "b", "c", "d", "e"};
        Stream 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);

    }

}

出力

java.lang.IllegalStateException: stream has already been operated upon or closed
    at java.util.stream.AbstractPipeline.(AbstractPipeline.java:203)
    at java.util.stream.ReferencePipeline.(ReferencePipeline.java:94)
    at java.util.stream.ReferencePipeline$StatelessOp.(ReferencePipeline.java:618)
    at java.util.stream.ReferencePipeline$2.(ReferencePipeline.java:163)
    at java.util.stream.ReferencePipeline.filter(ReferencePipeline.java:162)
    at com.hostingcompass.whois.range.run.TestJava8.main(TestJava8.java:25)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

2. 例–ストリームを再利用する

何らかの理由で、本当にストリームを再利用したい場合は、次のSupplierソリューションを試してください。

TestJava8.java

package com.example.java8;

import java.util.function.Supplier;
import java.util.stream.Stream;

public class TestJava8 {

    public static void main(String[] args) {

        String[] array = {"a", "b", "c", "d", "e"};

        Supplier> 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);

    }

}

出力

a
b
c
d
e
1

get()は、新しいストリームを返します。

Why?
テストのためにストリームを再利用する必要がある理由を教えてください。