Skip to content
閲覧中:
5. 並列Streamの挙動(66-75)

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)」 に進みますか?ここが合格への最後の仕上げになります。