17

stream.spliterator()は暗黙的に を閉じますかstream、それとも後で明示的に閉じる必要がありますか?

Stream<String> stream = Stream.of("a", "b", "c");
Spliterator<T> spliterator = stream.spliterator();
// Some low lever operation with the spliterator
stream.close(); // do we need to close?

一見すると、この.spliterator()メソッドは を閉じているように見えますが、streamは呼び出されていませんstream.close()。少なくとも、メソッドが呼び出された後にすぐに閉じると.spliterator()、スプリッテレータ操作には影響がないようです。

Stream<String> stream = Stream.of("a", "b", "c").limit(2);
Spliterator<T> spliterator = stream.spliterator();
stream.close();
// Some low lever operation with the spliterator

この質問はstream、たとえば.findAny().

stream.findAny() // Can I assume that I don't need to close the stream?
stream.onClose(() -> System.out.println("hi!")).findAny()`
// when the `onClose()` action will be called?

その質問の理由は、stream明示的に閉じる必要がある場合と、明示的に閉じる必要がない場合に、onClose()定義されたアクションがいつ実行されるかを明確にするためです。

4

4 に答える 4

12

端末操作はストリームを閉じません。閉鎖は手動で行う必要があります。自動クローズが発生する唯一の場所はflatMap操作内であり、通常オンザフライで作成されたサブストリームを手動でクローズすることは、困難から不可能の間のどこかです。

これはメソッドにも当てはまりますStream.spliterator()。あなたの例では、経由で作成されたストリームをStream.of(…)閉じる必要がなくonClose()、デフォルトで操作が登録されていないため、違いはありません。

ストリームをいつ閉じる必要があるかを調べるには、ファクトリ メソッドのドキュメントを参照する必要があります。のようにFiles#lines(Path, Charset)

ストリームに対する収集操作は、ストリームと基になるリソースを閉じますか?も参照してください。またはJava 8Stream.iterator()は、ストリームが完了すると自動的に閉じますか?

于 2017-10-11T13:15:42.630 に答える
4

spliterator()メソッドへの呼び出しSpliteratorは、このストリームの要素とその端末操作の a を返します。

あなたの質問に答えるには - いいえ、spliteratorメソッドまたはそのために、他の端末操作もストリームを閉じません。

これは、ターミナル操作について次のように文書化されています-

ターミナル操作が実行されると、ストリーム パイプラインは消費されたと見なされ、使用できなくなります。ほとんどの場合、ターミナル操作はeagerであり、データ ソースの走査とパイプラインの処理を完了してから戻ります。端末操作iterator()spliterator()のみがそうではありません。これらは、既存の操作がタスクに対して十分でない場合に、任意のクライアント制御のパイプライン トラバーサルを有効にする「エスケープ ハッチ」として提供されます。

もう一方の手を閉じるとStream、ドキュメントには次のように記載されています:-

ほとんどのストリーム インスタンスは、特別なリソース管理を必要としないコレクション、配列、または生成関数によってサポートされているため、使用後に実際に閉じる必要はありません。一般に、ソースが IO チャネル ( によって返されるものなど) であるストリームのみをFiles.lines(Path)閉じる必要があります。


それAutoCloseableに一致する状態-

すべてのサブクラスまたはインスタンスが解放可能なリソースを保持するわけではありませんが、基底クラスが AutoCloseable を実装することは可能であり、実際には一般的です。

これは BaseStream がそれを拡張する方法であり、close()などのリソースを使用するストリームよりもはるかに大きな影響を与えませんFiles.lines(...)

ただし、I/O ベースのフォームと非 I/O ベースのフォームの両方をサポートする Stream などの機能を使用する場合、非 I/O ベースのフォームを使用する場合、try-with-resources ブロックは通常不要です。

于 2017-10-11T13:16:15.720 に答える