yohhoyの日記

技術的メモをしていきたい日記

Stream APIの分類学

Java 8で導入されたStream APIの分類についてメモ。

ストリーム型

java.lang.streamパッケージでは4種類のインタフェースが提供される。いずれもBaseStream<T,S>インタフェースを継承する。

インタフェース 用途
Stream<T> T型ストリーム(ジェネリクス
IntStream プリミティブ型intストリーム
LongStream プリミティブ型longストリーム
DoubleStream プリミティブ型doubleストリーム

ストリームパイプライン中の中間操作*1により、任意のストリーム型相互変換が可能。

ストリームパイプライン構成要素

ストリームパイプライン(stream pipeline)は、1個の「ソース」、0個以上の「中間操作」、1個の「終端操作」から構成される。ソースと中間操作はストリーム型を返すため、メソッドチェイン形式で処理をつなげてストリームパイプラインを表現する。ストリームパイプラインの動作は、ソースまたは中間操作*2が提供するスプリッテレータSpliterator特性とストリーム特性、それぞれの中間操作および終端操作の種別から、それらの組み合わせに応じて決定される。

  • スプリッテレータ(spliterator)特性
    • 有限長(SIZED, SUBSIZED)/無限
    • 整列済み(SORTEDかつORDERED)/順序付け(ORDERED)/非順序付け
    • 変更不可(IMMUTABLE)/並行変更可能(CONCURRENT)/その他
    • 一意性保証(DISTINCT)/保証なし
    • 非null保証(NONNULL)/null許容
  • ストリーム(stream)特性
    • 順次処理ストリーム(sequential)
    • 並列処理ストリーム(parallel)
  • 中間操作(intermediate operation)
    • ステートレス(stateless)操作
    • ステートフル(stateful)操作: distinct(), sorted(), skip(), limit()
    • 短絡(short-circuiting)操作: limit()
    • 副作用(side-effect)操作: peek()
  • 終端操作(terminal operation)
    • リダクション操作
      • 並行リダクション(concurrent reduction): collect()(一定条件を満たすとき)
      • 可変リダクション(mutable reduction): collect()
      • リダクション(reduction)
    • 短絡(short-circuiting)操作: anyMatch(), allMatch(), noneMatch(), findFirst(), findAny()
    • 副作用(side-effect)操作: forEach(), forEachOrdered()
    • その他: iterator(), spliterator()

コレクタ構成要素

終端操作の一種、リダクション操作はCollector<T,A,R>インタフェースにより一般化される。コレクタ(collector)は、サプライヤ関数+アキュムレータ関数+コンバイナ関数+フィニッシャ関数と、コレクタ特性にて記述される。

  • サプライヤ(supplier)関数: 空の可変結果コンテナ型Aの供給(() -> A
  • アキュムレータ(accumulator)関数: 可変結果コンテナ型Aへの要素型Tの蓄積処理(A + T -> void
  • コンバイナ(combiner)関数: 2つの可変結果コンテナ型Aの結合演算(A + A -> A
  • フィニッシャ(finisher)関数: 最終的な可変結果コンテナ型Aから結果コンテナRへの変換(A -> R

コレクタは下記コレクタ特性Collector.Characteristicsの和集合を持つ。

  • 並行コレクタ(CONCURRENT): アキュムレータ関数を並行呼出可能(可変結果コンテナAがスレッドセーフ)*3
  • 非順序コレクタ(UNORDERED): 入力順序を維持しない(結果コンテナRが順序性を維持しない)*4
  • 恒等フィニッシャ(IDENTITY_FINISH): フィニッシャ関数を省略可能(Collector<T,R,R>

関連URL

*1:boxedメ ソッド, asXxxStream 系メソッド, mapToXxx 系メソッド

*2:ソースがスプリッテレータを定義する。ただし一部のステートフル操作や短絡操作により、ソースとは異なるスプリッテレータに変化するケースも存在する。

*3:コレクタの CONCURRENT 特性は並行リダクション動作の必要条件である。

*4:コレクタの UNORDERED 特性またはストリームの非順序性(スプリッテレータの非 ORDERED 特性)は、並行リダクション動作の必要条件である。