モジュール java.base
パッケージ java.util.stream

インタフェースStream<T>

型パラメータ:
T - ストリーム要素の型
すべてのスーパー・インタフェース:
AutoCloseable, BaseStream<T,Stream<T>>

public interface Stream<T> extends BaseStream<T,Stream<T>>
順次および並列の集約操作をサポートする要素のシーケンスです。 次の例は、StreamIntStreamを使用する集計操作を示したものです。

     int sum = widgets.stream()
                      .filter(w -> w.getColor() == RED)
                      .mapToInt(w -> w.getWeight())
                      .sum();
 
この例では、widgetsCollection<Widget>です。 Collection.stream()経由でWidgetオブジェクトのストリームが作成され、その結果がフィルタリングされて赤色のウィジェットのみを含むストリームが生成された後、それが、各赤色ウィジェットの重量を表すint値のストリームに変換されます。 続いてこのストリームが合計され、合計重量が生成されます。

オブジェクト参照のストリームであるStreamのほかに、IntStreamLongStreamおよびDoubleStream用のプリミティブ特殊化も存在しており、これらもすべてストリームと呼ばれ、ここで記述する特性や制限に準拠します。

計算を実行できるように、複数のストリーム操作を組み合わせて1つのストリーム・パイプラインが形成されます。 ストリーム・パイプラインは、1つのソース(配列、コレクション、ジェネレータ関数、入出力チャネルなど)、0個以上の中間操作(filter(Predicate)など、あるストリームを別のストリームに変換する操作)および1つの終端操作(count()forEach(Consumer)など、結果または副作用を生成する操作)から構成されます。 ストリームは遅延処理されます。ソース・データに対する計算は終端操作が起動されるまで実行されず、ソース要素も必要なだけしか消費されません。

ストリーム実装では、結果の計算を最適化する際にかなりの緯度が許可されます。 たとえば、ストリーム実装は、ストリーム・パイプラインから操作(または全ステージ)を自由に除去できます -- したがって、行動パラメータの呼び出しを無効にします -- 計算の結果に影響しないことを証明できる場合。 これは、特に(端末操作forEachおよびforEachOrderedなどによる)が指定されていないかぎり、動作パラメータの副作用が常に実行されるわけではなく、依存すべきではないことを意味します。 (このような最適化の具体的な例は、count()操作に記載されているAPIノートを参照してください。 詳細は、ストリーム・パッケージのドキュメントのside-effectsの項を参照してください。)

コレクションとストリームは、表面上似た点があるものの、異なる目的を持っています。 コレクションは主に、要素の効率的な管理やアクセスに注力しています。 これに対し、ストリームは要素の直接アクセスや操作の手段を持たず、代わりにソースやそのソースに対して集約的に実行される計算操作を宣言的に記述することに注力しています。 ただし、用意されたストリーム操作が必要な機能を提供しない場合には、BaseStream.iterator()およびBaseStream.spliterator()操作を使って制御されたトラバーサルを実行することもできます。

ストリーム・パイプラインは、上の「widgets」の例のように、ストリーム・ソースに対する問合せとみなすことができます。 ソースが明示的に同時変更向けに設計されたもの(ConcurrentHashMapなど)でないかぎり、ストリームのソースを照会中に変更すると、予測不可能な動作や間違った動作が発生する可能性があります。

ほとんどのストリーム操作は、上の例でmapToIntに渡されたラムダ式w -> w.getWeight()のような、ユーザー指定の動作を記述するパラメータを受け取ります。 正しい動作を維持するには、これらの動作パラメータは次を満たす必要があります。

  • 非干渉でなければいけない(ストリームのソースを変更しない)、および
  • ほとんどの場合、ステートレスでなければいけない(その結果は、ストリーム・パイプラインの実行中に変化する可能性のあるどの状態にも依存すべきでない)。

そのようなパラメータは常に関数型インタフェース(Functionなど)のインスタンスであり、通常はラムダ式やメソッド参照になります。 特に明記されていないかぎり、これらのパラメータはnull以外でなければいけません。

(中間または終端ストリーム操作を呼び出して)ストリームを操作するのは、一度だけにすべきです。 このため、たとえば同じソースが2つ以上のパイプラインに対してデータを供給する「フォークされた」ストリームや、同じストリームを複数回トラバースすることなどは、禁止されます。 ストリーム実装は、ストリームが再利用されているのを検出すると、IllegalStateExceptionをスローします。 ただし、一部のストリーム操作からは新しいストリーム・オブジェクトではなくレシーバが返されることがあるため、場合によっては再利用を検出できない可能性があります。

ストリームはBaseStream.close()メソッドを持ち、AutoCloseableを実装します。 ストリームが閉じられた後でストリームを操作すると、IllegalStateExceptionがスローされます。 ほとんどのストリーム・インスタンスは、特別なリソース管理を必要としないコレクション、配列または生成関数によってバックアップされるため、使用後にクローズする必要はありません。 一般に、ソースがIOチャネルであるストリーム(Files.lines(Path)によって返されるストリームなど)のみ、クローズが必要です。 ストリームを閉じる必要がある場合は、try-with-resources文または同様の制御構造内のリソースとして開いて、操作の完了後にすぐに閉じられるようにする必要があります。

ストリーム・パイプラインは順次、並列のいずれかで実行できます。 この実行モードは、ストリームのプロパティの1つです。 ストリームの作成時には、順次実行または並列実行の初期選択が行われます。 (たとえば、Collection.stream()では順次ストリームが作成され、Collection.parallelStream()では並列ストリームが作成されます。) この実行モードの選択を変更するにはBaseStream.sequential()またはBaseStream.parallel()メソッドを使用し、実行モードを照会するにはBaseStream.isParallel()メソッドを使用します。

導入されたバージョン:
1.8
関連項目: