public interface Stream<T> extends BaseStream<T,Stream<T>>
Stream
とIntStream
を使った集計処理を示す。
int sum = widgets.stream()
.filter(w -> w.getColor() == RED)
.mapToInt(w -> w.getWeight())
.sum();
この例ではwidgets
はCollection<Widget>
である。ここではWidget
オブジェクトのストリームをCollection.stream()
で作成し、赤いウィジェットのみを含むストリームを作成するために絞り込み、それを赤い各ウィジェットの重さを表すint
のストリームに変換する。そして重さの総計を求めるためにこのストリームの和が求められる。 オブジェクトへの参照のストリームであるStream
に加えて、プリミティブ値に特化したIntStream
, LongStream
, DoubleStream
もあり、これらは全てが「ストリーム」と呼ばれ、ここに示される全ての特性と制約を満たす。
計算を実行するために、ストリーム処理は組み立てられて1つのストリームパイプラインへと合成される。ストリームパイプラインは情報源(source、配列・コレクション・生成関数・I/Oチャンネルなど)、零個以上の中間処理(intermediate operations)(filter(Predicate)
のようにストリームを別のストリームに変換する)、末端処理(terminal operation)(count()
やforEach(Consumer)
のように結果や副作用を生成する)からなる。ストリームは遅延的(lazy)である。つまり情報源のデータに対する計算は末端処理が開始された際にのみ実行され、情報源の要素は必要になったときに消費される。
コレクションとストリームは表面上の類似点はあるものの、異なる目的を持つ。コレクションはその要素の効率的な管理とその要素への効率的なアクセスに主に注意を注ぐ。対照的に、ストリームは要素へ直接アクセスする手段や要素を直接操作する手段を備えておらず、代わりに情報源と、情報源に対してまとめて実行される計算処理を宣言的に示すことに注意を注ぐ。ただし、用意されたストリーム演算に望む機能がない場合、走査の制御のためにBaseStream.iterator()
演算とBaseStream.spliterator()
演算が利用できる。
上記の「ウィジェット」の例のようなストリームパイプラインはストリーム源に対する問い合わせとして見ることもできる。情報源が(ConcurrentHashMap
などのように)並行的な変更のために特別に設計されている場合を除き、問い合わせ中にストリーム源を変更すると予測できない挙動や誤った挙動となる場合がある。
ほとんどのストリーム処理はユーザが指定する挙動を表わすパラメータを受け取る。上の例においてmapToInt
に渡されるラムダ式w -> w.getWeight()
などである。正しい動作を保つため、それらの挙動パラメータ(behavioral parameters)は次の条件を満たす必要がある。
このようなパラメータは常に関数的インターフェース(functional interface)のインスタンスであり、多くの場合ラムダ式やメソッド参照である。特に別記されてない限り、それらのパラメータはnullではいけない。
ストリームは一度だけ利用する(中間処理や末端処理を呼び出す)べきである。これは例えば「分岐」したストリームを認めない、つまり同じ情報源から複数のパイプラインに要素を供給したり、同じストリームを複数回走査するといったことを認めないということである。ストリームの実装はストリームが再利用されているのを検知した場合、IllegalStateException
を投げる場合がある。しかし、ある種のストリーム演算は新しいストリームオブジェクトではなくレシーバを返すため、再利用を常に検知できるとは限らない。
ストリームはBaseStream.close()
メソッドを持ち、AutoCloseable
を実装するが、ほとんど全てのストリームのインスタンスは実際には利用後に閉じる必要はない。一般的に、情報源がI/Oチャンネルであるようなストリーム(Files.lines(Path, Charset)
が返すストリームなど)のみ閉じる必要がある。ほとんどのストリームはコレクション・配列・生成関数が元になっており、特別な資源管理を必要としない(もしストリームを閉じる必要がある場合、try
-with-resources文の資源として宣言できる)。
ストリームパイプラインは逐次的に実行される場合と並列に実行される場合がある。この実行モードはストリームの特性である。ストリームは逐次実行か並列実行か選択されて作成される(例えば、Collection.stream()
は逐次ストリームを作成し、Collection.parallelStream()
は並列ストリームを作成する)。この実行モードの選択はBaseStream.sequential()
メソッドやBaseStream.parallel()
メソッドで変更でき、BaseStream.isParallel()
メソッドで調べられる。
修飾子とタイプ | インタフェースと説明 |
---|---|
static interface |
Stream.Builder<T>
Stream の可変なビルダこれにより要素を個別に生成してStreamBuilder へ追加して(ArrayList を一時バッファとして使った場合の複製のオーバーヘッド無しに)Stream を作成できるようになる。 |
修飾子とタイプ | メソッドと説明 |
---|---|
boolean |
allMatch(Predicate<? super T> predicate)
このストリームの全ての要素が与えられた述語に適合するか返す。
|
boolean |
anyMatch(Predicate<? super T> predicate)
このストリームのある要素が与えられた述語に適合するか返す。
|
static <T> Stream.Builder<T> |
builder()
Stream のビルダを返す。 |
<R,A> R |
collect(Collector<? super T,A,R> collector)
Collector を使ってこのストリームの要素に可変的簡約を実行する。 |
<R> R |
collect(Supplier<R> supplier,
BiConsumer<R,? super T> accumulator,
BiConsumer<R,R> combiner)
このストリームの要素に可変的簡約を実行する。
|
static <T> Stream<T> |
concat(Stream<? extends T> a,
Stream<? extends T> b)
ストリームの要素が、最初のストリームの全ての要素の後に2つ目のストリームの全ての要素を並べたような、遅延的に連結されたストリームを返す。
|
long |
count()
このストリームの要素数を返す。
|
Stream<T> |
distinct()
このストリームの要素のうち(
Object.equals(Object) に従って)重複を除いた要素からなるストリームを返す。 |
static <T> Stream<T> |
empty()
空の逐次的
Stream を返す。 |
Stream<T> |
filter(Predicate<? super T> predicate)
このストリームの要素のうち、与えられた述語に適合する要素からなるストリームを返す。
|
Optional<T> |
findAny()
このストリームのある要素を表す
Optional 、もしくはストリームが空であれば空のOptional を返す。 |
Optional<T> |
findFirst()
このストリームの最初の要素を表す
Optional 、もしくはストリームが空であれば空のOptional を返す。 |
<R> Stream<R> |
flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
与えられた写像関数をこのストリームの各要素に適用して生成したストリームの内容で各要素を置き換えた結果からなるストリームを返す。
|
DoubleStream |
flatMapToDouble(Function<? super T,? extends DoubleStream> mapper)
与えられた写像関数をこのストリームの各要素に適用して生成したストリームの内容で各要素を置き換えた結果からなる
DoubleStream を返す。 |
IntStream |
flatMapToInt(Function<? super T,? extends IntStream> mapper)
与えられた写像関数をこのストリームの各要素に適用して生成したストリームの内容で各要素を置き換えた結果からなる
IntStream を返す。 |
LongStream |
flatMapToLong(Function<? super T,? extends LongStream> mapper)
与えられた写像関数をこのストリームの各要素に適用して生成したストリームの内容で各要素を置き換えた結果からなる
LongStream を返す。 |
void |
forEach(Consumer<? super T> action)
このストリームの各要素にアクションを適用する。
|
void |
forEachOrdered(Consumer<? super T> action)
このストリームの各要素にアクションを適用する。
|
static <T> Stream<T> |
generate(Supplier<T> s)
各要素が
Supplier によって生成される、逐次的な無限Stream を返す。 |
static <T> Stream<T> |
iterate(T seed,
UnaryOperator<T> f)
初期要素
seed に対する関数f の繰り返しの適用によって生成された無限Stream を返す。 |
Stream<T> |
limit(long maxSize)
このストリームの要素からなり、長さが
maxSize より長くならないように切り詰められたストリームを返す。 |
<R> Stream<R> |
map(Function<? super T,? extends R> mapper)
このストリームの要素に与えられた関数を適用した結果からなるストリームを返す。
|
DoubleStream |
mapToDouble(ToDoubleFunction<? super T> mapper)
このストリームの要素に与えられた関数を適用した結果からなる
DoubleStream を返す。 |
IntStream |
mapToInt(ToIntFunction<? super T> mapper)
このストリームの要素に与えられた関数を適用した結果からなる
IntStream を返す。 |
LongStream |
mapToLong(ToLongFunction<? super T> mapper)
このストリームの要素に与えられた関数を適用した結果からなる
LongStream を返す。 |
Optional<T> |
max(Comparator<? super T> comparator)
このストリームの最大要素を
Comparator に従って返す。 |
Optional<T> |
min(Comparator<? super T> comparator)
このストリームの最小要素を
Comparator に従って返す。 |
boolean |
noneMatch(Predicate<? super T> predicate)
このストリームのどの要素も与えられた述語に適合しないか返す。
|
static <T> Stream<T> |
of(T... values)
要素が指定された値であるような逐次的なストリームを返す。
|
static <T> Stream<T> |
of(T t)
1つの要素を含む逐次的な
Stream を返す。 |
Stream<T> |
peek(Consumer<? super T> action)
このストリームの要素からなり、加えて結果のストリームから要素が消費されるごとにその要素にアクションを実行するストリームを返す。
|
Optional<T> |
reduce(BinaryOperator<T> accumulator)
|
T |
reduce(T identity,
BinaryOperator<T> accumulator)
|
<U> U |
reduce(U identity,
BiFunction<U,? super T,U> accumulator,
BinaryOperator<U> combiner)
与えられた単位元と、累積関数と統合関数を使って、このストリームの要素に簡約処理を実行して簡約された値を返す。
|
Stream<T> |
skip(long n)
このストリームの
n 個の要素を取り除いた残りの要素からなるストリームを返す。 |
Stream<T> |
sorted()
このストリームの要素を、自然順に整列した結果からなるストリームを返す。
|
Stream<T> |
sorted(Comparator<? super T> comparator)
このストリームの要素を、与えらえた
Comparator に従って整列した結果からなるストリームを返す。 |
Object[] |
toArray()
このストリームの要素からなる配列を返す。
|
<A> A[] |
toArray(IntFunction<A[]> generator)
このストリームの要素からなる配列を返す。
|
close, isParallel, iterator, onClose, parallel, sequential, spliterator, unordered
Stream<T> filter(Predicate<? super T> predicate)
これは中間処理である。
<R> Stream<R> map(Function<? super T,? extends R> mapper)
これは中間処理である。
IntStream mapToInt(ToIntFunction<? super T> mapper)
IntStream
を返す。 これは中間処理である。
LongStream mapToLong(ToLongFunction<? super T> mapper)
LongStream
を返す。 これは中間処理である。
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper)
DoubleStream
を返す。 これは中間処理である。
LongStream flatMapToLong(Function<? super T,? extends LongStream> mapper)
DoubleStream flatMapToDouble(Function<? super T,? extends DoubleStream> mapper)
Stream<T> distinct()
Object.equals(Object)
に従って)重複を除いた要素からなるストリームを返す。 順序を持つストリームの場合、重複を除いた要素の選択は安定的である(重複する要素の場合、出現順で最初に表われた要素が保存される)。順序を持たないストリームの場合、安定性は保障されない。
これは状態を持つ中間処理である。
Stream<T> sorted()
Comparable
でなければ、末端処理を実行した際にjava.lang.ClassCastException
が投げられる場合がある。 順序を持つストリームに対して、整列は安定的である。順序を持たないストリームに対して、安定性の保障は成されない。
これは状態を持つ中間処理である。
Stream<T> sorted(Comparator<? super T> comparator)
Comparator
に従って整列した結果からなるストリームを返す。 順序を持つストリームに対して、整列は安定的である。順序を持たないストリームに対して、安定性の保障は成されない。
これは状態を持つ中間処理である。
Stream<T> peek(Consumer<? super T> action)
これは中間処理である。
並列ストリームパイプラインの場合、アクションは上流の処理から利用可能になった際に任意の時間と任意のスレッドで呼ばれる。もしアクションが共有状態を変更した場合、必要な同期を用意する必要がある。
Stream<T> limit(long maxSize)
maxSize
より長くならないように切り詰められたストリームを返す。 これは短絡的で状態を持つ中間処理である。
void forEach(Consumer<? super T> action)
これは末端処理である。
この処理の挙動は非決定的であると明示的に定められている。並列ストリームパイプラインの場合、この処理はストリームの出現順順序を尊重するとは限らない。そのようにしてしまうと並列処理の利点を犠牲にしてしまうためである。与えられた要素に対して、アクションはライブラリが選んだ任意の時間と任意のスレッドで実行される。もしアクションが共有状態を変更するならば、アクションは必要な同期処理を用意する責任を負う。
void forEachOrdered(Consumer<? super T> action)
これは末端処理である。
この処理では出現順順序がある場合、出現順に従って要素を一度に1つずつ処理する。1つの要素へのアクションは続く要素に対するアクションの実行の前に発生(happens-before)するが、与えられた要素に対してアクションはライブラリが選択した任意のスレッドで実行される。
Object[] toArray()
これは末端処理である。
<A> A[] toArray(IntFunction<A[]> generator)
generator
関数を使って返り値の配列や、分割実行やリサイズ時に必要となる配列を確保する。 これは末端処理である。
T reduce(T identity, BinaryOperator<T> accumulator)
T result = identity;
for (T element : this stream)
result = accumulator.apply(result, element)
return result;
ただし逐次的に実行されるとは制約されていない。 値identity
は累積関数の単位元である必要がある。つまり、任意のt
に対してaccumulator.apply(identity, t)
はt
と等しい。accumulator
関数は結合的関数である必要がある。
これは末端処理である。
Optional<T> reduce(BinaryOperator<T> accumulator)
Optinoal
を返す。これは次と等しい。
boolean foundAny = false;
T result = null;
for (T element : this stream) {
if (!foundAny) {
foundAny = true;
result = element;
}
else
result = accumulator.apply(result, element);
}
return foundAny ?Optional.of(result) : Optional.empty();
ただし逐次的に実行されるとは制約されていない。 accumulator
関数は結合的関数である必要がある。
これは末端処理である。
<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
U result = identity;
for (T element : this stream)
result = accumulator.apply(result, element)
return result;
ただし逐次的に実行されるとは制約されていない。 値identity
は統合関数の単位元である必要がある。つまり任意のu
に対して、combiner.apply(identity, u)
がu
に等しいということである。加えて、combiner
関数はaccumulator
関数と適合する必要がある。つまり任意のu
とt
について次の式が成り立つ必要がある。
combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)
これは末端処理である。
<R> R collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)
ArrayList
などの可変な結果コンテナであるものであり、結果を置き換えるのではなく結果の状態を変更して各要素を組み入れるような簡約である。これは次のコードと同じ結果を生成する。
R result = supplier.get();
for (T element : this stream)
accumulator.accept(result, element);
return result;
reduce(Object, BinaryOperator)
のように、collect
処理は追加の同期処理を必要とせずに並列化できる。
これは末端処理である。
<R,A> R collect(Collector<? super T,A,R> collector)
Collector
を使ってこのストリームの要素に可変的簡約を実行する。Collector
はcollect(Supplier, BiConsumer, BiConsumer)
の引数として使われる関数をカプセル化し、収集戦略の再利用を可能にすると共に、複数レベルのグループ化や組分けなどといった風に収集処理の合成を可能にする。 もしストリームが並列で、Collector
が並行的
であり、ストリームが順序を持たないかコレクタが順序を持たない
場合、並行簡約が実行される(並行簡約についてはCollector
を見よ)。
これは末端処理である。
並列に実行された場合、可変なデータ構造の隔離を維持するために複数の中間結果がインスタンス化され、満たされ、併合される。そのため(ArrayList
などの)スレッドセーフでないデータ構造に対して並列に実行されたとしても、並列簡約のために追加の同期処理は必要ない。
long count()
boolean anyMatch(Predicate<? super T> predicate)
false
を返す。 これは短絡的で状態を持つ末端処理である。
boolean allMatch(Predicate<? super T> predicate)
true
を返す。 これは短絡的で状態を持つ末端処理である。
boolean noneMatch(Predicate<? super T> predicate)
true
を返す。 これは短絡的で状態を持つ末端処理である。
Optional<T> findFirst()
Optional
、もしくはストリームが空であれば空のOptional
を返す。このストリームが出現順順序を持たなければ任意の要素が返される場合がある。 これは短絡的で状態を持つ末端処理である。
Optional<T> findAny()
Optional
、もしくはストリームが空であれば空のOptional
を返す。 これは短絡的で状態を持つ末端処理である。
この処理の動作は明示的に非決定的であり、どの要素を選んでもよい。これにより並列実行時の性能を最大化できる。その際のコストは同じ情報源に対する複数回の呼び出しが同じ値を返さないことである(もし安定した結果を望むならば、代わりにfindFirst()
を用いよ)。
static <T> Stream.Builder<T> builder()
Stream
のビルダを返す。
static <T> Stream<T> empty()
Stream
を返す。
static <T> Stream<T> of(T t)
Stream
を返す。
@SafeVarargs static <T> Stream<T> of(T... values)
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)
seed
に対する関数f
の繰り返しの適用によって生成された無限Stream
を返す。seed
, f(seed)
, f(f(seed))
などからなるストームを生成する。 Stream
の最初の要素(位置0
)はseed
によって与えられる。n > 0
に対しては、位置n
の要素はf
を位置n - 1
の要素に適用した結果である。
static <T> Stream<T> generate(Supplier<T> s)
Supplier
によって生成される、逐次的な無限Stream
を返す。定数のストリームや乱数のストリームなどを生成するのに向いている。