5. 並列Streamの挙動(66-75)
並列Stream(Parallel Stream)は、Java Gold試験において**「実行順序」と「パフォーマンスのトレードオフ」、そして「終端操作との組み合わせ」**が頻出するトピックです。
66番から75番までのコード例と、試験で狙われるポイントを解説します。
66-69: 並列化の基本と切り替え¶
Java
List<String> list = List.of("A", "B", "C", "D", "E");
// 66. parallel(): ストリームを途中で並列モードに切り替える
Stream<String> s66 = list.stream().parallel();
// 67. sequential(): 並列ストリームを順次モードに戻す
// 試験ポイント: 最後に呼び出した設定(parallelかsequentialか)が全体に適用される
Stream<String> s67 = list.stream().parallel().filter(s -> true).sequential();
// 68. isParallel(): 並列かどうかを判定する
boolean isParallel = s66.isParallel(); // true
// 69. unordered(): 順序の制約を排除する
// 試験ポイント: sorted()などの順序に依存する処理が不要な場合、並列処理が高速化する
list.stream().parallel().unordered().forEach(System.out::print);
70-72: 並列時の集約(reduce)と検索¶
Java
// 70. reduce(identity, accumulator, combiner)
// 第3引数の「Combiner(結合器)」は並列処理時のみ実行される
int totalLength = list.parallelStream().reduce(
0, // identity
(sum, str) -> sum + str.length(), // accumulator (各スレッド内)
(sum1, sum2) -> sum1 + sum2 // combiner (スレッド間の統合)
);
// 71. identityの性質
// 並列処理では「op(identity, x) == x」でなければ計算結果が壊れる
// 例:初期値を「10」にすると、スレッド数に応じて10が複数回加算され結果が不定になる
// 72. findFirst vs findAny
// 試験ポイント: 並列時、findFirstは「最初の要素」を特定するためコストがかかる
// findAnyは「最初に見つかったスレッドの要素」を返すため、並列時に非常に高速
Optional<String> any = list.parallelStream().findAny();
73-75: 副作用と分割¶
Java
// 73. 並列時の副作用(Side Effects)
// 試験ポイント: Stream外の変数(非スレッドセーフなListなど)を書き換えるのは禁止
List<Integer> sideEffectList = new ArrayList<>();
IntStream.range(0, 100).parallel().forEach(sideEffectList::add);
// 結果: Listのサイズが100にならない、または例外が発生する可能性がある
// 74. Spliterator: Streamの分割用イテレータ
// カスタムストリームの並列処理を制御する際に使用
Spliterator<String> split1 = list.spliterator();
Spliterator<String> split2 = split1.trySplit(); // 半分に分割
// 75. ステートフル中間操作
// sorted(), distinct(), limit() などは全要素を一度見る必要があるため、
// 並列処理のメリットが相殺されやすい
list.parallelStream().sorted().forEach(System.out::print);
💡 Java Gold 試験対策の急所¶
1. forEach vs forEachOrdered¶
forEach: 並列処理の場合、出力順序はバラバラになります。forEachOrdered: 並列処理であっても、ソース(Listなど)の順序に従って処理されます。ただし、並列化による速度メリットはほぼ失われます。
2. reduce の「結合器(Combiner)」¶
試験のコードで reduce の引数が3つある場合、それは並列処理を意識したものです。
(sum1, sum2) -> sum1 + sum2この部分が正しく記述されているか、型が一致しているかが問われます。
3. 並列化しても速くならないケース¶
- データ量が少ない場合(オーバーヘッドの方が大きい)。
- ソースが
LinkedListの場合(分割コストが高い。ArrayListや配列は高速)。 - 中間操作に
limit()やsorted()が含まれる場合。
次は、最後のセクション 「Optionalとの連携」および「試験のひっかけ(76-100)」 に進みますか?ここが合格への最後の仕上げになります。