JavaOneレポートが挟まってしまいましたが、再び詳説Java SE 8に戻りましょう。
今月は第16回の続きで、もう1度パラレルストリームを取りあげます。まず、第16回で取りあげなかった、reduceメソッドについて説明し、その後パラレル処理のしくみについて解説します。
reduce
本連載の第6回でreduceメソッドには3種類のオーバーロードが存在することを示しました。第6回ではそのうち2種類を説明しましたが、もう1つのオーバーロードが残っています。
第6回で説明したreduceメソッドは、第1引数の初回値とストリームの要素の型が同一でなくてはなりませんでした。もう1つのreduceメソッドは初回値とストリームの要素の型が異なっているものです。
このreduceメソッドのシグネチャはリスト1のようになっています。
リスト1 reduceメソッドのシグネチャ
U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
初回値の型がUで、ストリームの要素の型がTになります。このため、第2引数のjava.util.function.BiFunctionインタフェースのacceptメソッドの引数は第1引数がU、第2引数がTになり、戻り値の型がUになります。
そして、第3引数としてjava.util.function.BinaryOperatorインタフェースのラムダ式が必要になります。第3引数のラムダ式では途中まで集約した値同士を集約するために使用します。このため、BinaryOperatorインタフェースのapplyメソッドの第1引数、第2引数、戻り値の型はすべてUになります。
たとえば、文字列のリストにおける、要素の文字列長の合計を求めるにはリスト2のように記述します。
リスト2 文字列長の合計を求める
List<String> words = ...;
Integer length = words.stream()
.reduce(0, (l, w) -> l + w.length(), (l1, l2) -> l1 + l2);
第2引数のラムダ式でそれまでの文字列長の合計と今回要素の文字列長を加えています。第3引数のラムダ式では文字列長の合計同士を足し合わせています。