Collectors ではないのだが reduce という操作の性質上いきなり終端処理となる
int sum = Stream.of(1, 2, 3, 4, 5).reduce( 0, // 初期値 (v1, v2) -> { // アキュムレータ System.out.println(v1); // 0, 1, 3, 6, 10 System.out.println(v2); // 1, 2, 3, 4, 5 return v1 + v2; }); System.out.println(sum); // 15
reduce の第1引数にはその集計の初期値を設定する。
第2引数には stream の要素の型の2つの引数を取るラムダを指定する。 ラムダの第1引数は ラムダが return した結果が入る、第2引数は stream の各要素が順々に格納されて呼び出される。 最初の1回はラムダの結果が無いので reduce 第1引数で指定した初期値が設定されるという仕掛けになっている。
第1引数の内容が全走査において保持されるので、これに対して値を集約していくことで全部の処理が完了する。
すべての要素を走査したらその結果が return される
stream の元要素と操作要素が全部一致していないといけないので地味に使い勝手が悪い。
この第2引数のラムダは accumulator(アキュムレータ) と呼ばれるもので個々の要素をどう集約するかを表している。
この reduce はこのような書き方もできる。
int sum = Stream.of(1, 2, 3, 4, 5).reduce( 0, // 初期値 (s, v) -> { // アキュムレータ return s + v; }, (sum1, sum2) -> { // コンバイナ return sum1 + sum2; } ); System.out.println(sum);
さらに引数が増えているがこの第3引数は combiner(コンバイナ) と呼ばれるもので集約した結果同士をどう集約するかを表している。 何がうれしいかというと stream 要素を並列に実行して個々の accumulator の結果を集約することができるので高いパフォーマンスが期待できるということになる。 しかし実行順序は無視されるので実行順が重要なアルゴリズムには使えない。