Java Gold SE11対策:命令型と宣言型の違いから学ぶStreamの本質

アイキャッチ画像

Java Gold SE11の試験では、Stream APIがなぜ導入されたのかという思想的な背景も問われます。
その本質を理解する鍵が「命令型(imperative)と宣言型(declarative)」の違いにあります。

本記事では、従来のforループとの違いから始まり、Streamのパイプライン構造、中間操作・終端操作、そして遅延評価の概念まで、Streamの基礎を論理的に解説します。

命令型と宣言型とは?

● 命令型(Imperative Programming)

何をするか」よりも「どうやるか」に重点を置いた書き方。

List<String> list = List.of(“apple”, “banana”, “apricot”);

List<String> result = new ArrayList<>();

for (String s : list) {

    if (s.startsWith(“a”)) {

        result.add(s.toUpperCase());

    }

}

  • 要素を1つずつ取り出す
  • 条件をifで書く
  • 結果を明示的にaddする

→ 開発者が逐次処理の手続きをすべて記述しています。

● 宣言型(Declarative Programming)

何をしたいか」に集中して、処理の流れは抽象化するスタイル。

List<String> result = list.stream()

    .filter(s -> s.startsWith(“a”))

    .map(String::toUpperCase)

    .collect(Collectors.toList());

  • 条件に合うものだけ選ぶ(filter)
  • 変換処理を行う(map)
  • 結果を収集する(collect)

何をするかの宣言に徹していて、「どうやってループを回すか」は書いていません。

Streamのパイプライン構造

Stream APIの最大の特徴は、中間操作 → 終端操作というパイプライン構造です。

list.stream()  // Streamの生成

    .filter(…)   // 中間操作

    .map(…)      // 中間操作

    .collect(…)  // 終端操作(ここで実行される!)

中間操作(Intermediate Operation)

  • Streamを変換・フィルタするが、まだ実行されない
  • 例:filter(), map(), sorted(), distinct()

終端操作(Terminal Operation)

  • Streamの計算を実行するタイミング
  • 例:collect(), forEach(), count()

forループとの違いを実感しよう

特徴forループStream
処理の記述方法明示的(命令型)宣言的
並列処理自力でスレッドを書く必要ありparallelStream()で対応可
中間処理の再利用性自分で変数・条件を書く必要ありmap/filterなどを組み合わせられる
処理の実行タイミング逐次即時実行遅延評価(後述)

Streamは構文的に短くなることが目的ではなく、抽象度を上げて可読性・柔軟性・並列性を得ることが本質です。

遅延評価(Lazy Evaluation)

JavaのStreamは、中間操作だけでは実行されません

Stream<String> s = list.stream()

    .filter(x -> {

        System.out.println(“filter: ” + x);

        return x.startsWith(“a”);

    });

// ここではまだ出力されない!

List<String> result = s.collect(Collectors.toList()); // ← ここで初めて実行

このように、終端操作が来るまで実行されない性質を**遅延評価(lazy evaluation)**と呼びます。

なぜ遅延評価?

  • 不要な要素を早めに捨てられる
  • 複数の中間操作を効率的に融合できる
  • 並列処理やショートサーキットがしやすい

例:limit(5) などを前に持ってくると、処理数を削減できる!

実務にも効くStreamの利点

利点内容
可読性の向上処理の目的が1行ずつ明確に分かれる
柔軟な組み合わせfilter → map → collect の順序変更や再利用が簡単
並列処理対応parallelStream()で並列処理も簡単に
不変性の促進元のリストを変更しないスタイルになる

まとめ:試験前に押さえておくべきポイント

試験論点チェック
宣言型と命令型の違いを説明できるか?
forループとstreamの処理構造の違いを理解しているか?
中間操作と終端操作の区別がつくか?
遅延評価の概念を説明できるか?
実行タイミングはcollectなどの終端操作であると知っているか?

おわりに

Streamは単なるループの置き換えではありません。「何をしたいのか」を明確にしながら、柔軟な処理の組み立てができるのが最大の魅力です。

Java Gold SE11の試験では、「なぜforではなくstreamなのか」といった前提理解を問う設問もあります。ぜひこの宣言型思考をしっかりと押さえてください!