1概要

この短い記事では、Java 8で

Stream

クラスを操作するときに発生する可能性がある一般的な

Exception

について説明します。

IllegalStateException: stream has already been operated upon or closed.

この例外が発生したときのシナリオ、およびそれを回避するための考えられる方法をすべて実用的な例と共に説明します。


2原因

Java 8では、各

Stream

クラスは使い捨てのデータシーケンスを表し、いくつかのI/O操作をサポートします。

_______________________________________________________________________________________________________________________________________________________________─────────────────――

Stream

が再利用されていることを検出すると、Stream実装は

IllegalStateException

をスローすることがあります。

端末操作が

Stream

オブジェクトに対して呼び出されるたびに、インスタンスは消費されて閉じられます。

そのため、

__

Stream ** を消費する単一の操作のみを実行することができます。

これを実際の例に変換する方法を見てみましょう。

Stream<String> stringStream = Stream.of("A", "B", "C", "D");
Optional<String> result1 = stringStream.findAny();
System.out.println(result1.get());
Optional<String> result2 = stringStream.findFirst();

結果として:

A
Exception in thread "main" java.lang.IllegalStateException:
  stream has already been operated upon or closed


#findAny()

メソッドが呼び出された後、

stringStream

が閉じられるため、

Stream

に対するそれ以上の操作は

IllegalStateException

をスローします。これは

#findFirst()

メソッドの呼び出し後に行われたことです。

===

3ソリューション

簡単に言うと、解決策は必要になるたびに新しい

Stream

を作成することです。

もちろん、手動で行うこともできますが、それが

Supplier

機能インターフェースが本当に便利になるところです。

Supplier<Stream<String>> streamSupplier
  = () -> Stream.of("A", "B", "C", "D");
Optional<String> result1 = streamSupplier.get().findAny();
System.out.println(result1.get());
Optional<String> result2 = streamSupplier.get().findFirst();
System.out.println(result2.get());

結果として:

A
A


streamSupplier

オブジェクトは

Stream <String>

型で定義しました。これは

#get()

メソッドが返す型とまったく同じです。

Supplier

は、入力を受け取らず、新しい

Stream

を返すラムダ式に基づいています。


Supplier

で機能メソッド

get()

を呼び出すと、新しく作成された

Stream

オブジェクトが返されます。このオブジェクトに対して別の

Stream

操作を安全に実行できます。

===

5結論

このクイックチュートリアルでは、

Stream

が既に閉じられているか操作されているときにスローされる有名な

IllegalStateException

を回避しながら、

Stream

で端末操作を複数回実行する方法を説明しました。


GitHubについて

では、完全なソースコードとすべてのコードスニペットを見つけることができます。