2.1.1 stream api中間操作、終端操作
JavaのStream APIは、データ集合(Collectionなど)を効率的に処理するための非常に強力なツールです。
Stream APIの操作は、大きく分けて**「中間操作」と「終端操作」**の2種類に分類されます。これらは「パイプライン」を構成するパーツのようなものです。
1. 中間操作と終端操作の決定的な違い¶
もっとも大きな違いは、**「その操作がStreamを返すか、結果を返すか」**にあります。
| 特徴 | 中間操作 (Intermediate Operations) | 終端操作 (Terminal Operations) |
|---|---|---|
| 戻り値 | 新しい Stream を返す | 結果(List, int, voidなど)を返す |
| 連続性 | メソッドチェーンで繋げられる | 繋げられない(ここで処理が終了する) |
| 実行タイミング | 遅延実行(終端操作が呼ばれるまで動かない) | 呼び出された瞬間に全処理が実行される |
2. 主な中間操作(加工・抽出)¶
中間操作は、元のデータをフィルタリングしたり、別の形に変換したりします。
filter(Predicate): 条件に合う要素だけを抽出します。-
例:
s -> s.startsWith("A")(Aで始まるものだけ残す) -
map(Function): 各要素を別の値に変換します。 -
例:
String::toUpperCase(小文字を大文字に変換) -
sorted(): 要素を並び替えます。 distinct(): 重複する要素を除去します。limit(long): 先頭から指定した数だけ取得します。
3. 主な終端操作(集計・出力)¶
終端操作を実行すると、Streamは閉じられ、再利用できなくなります。
forEach(Consumer): 各要素に対して処理を実行します(戻り値なし)。collect(Collector): 結果をリストやセットなどのコレクションにまとめます。-
例:
Collectors.toList() -
count(): 要素の数を数えます。 reduce(BinaryOperator): 全要素を1つの値にまとめます(合計値や最大値など)。anyMatch / allMatch / noneMatch: 条件に一致するかどうかを判定し、booleanを返します。
4. 実際のコード例¶
以下のコードで、中間操作と終端操作の流れを確認してみましょう。
Java
import java.util.List;
import java.util.Arrays;
import java.util.stream.Collectors;
List<String> names = Arrays.asList("apple", "banana", "apricot", "cherry");
List<String> result = names.stream()
.filter(s -> s.startsWith("a")) // 中間操作:抽出
.map(String::toUpperCase) // 中間操作:変換
.sorted() // 中間操作:並び替え
.collect(Collectors.toList()); // 終端操作:リスト化
System.out.println(result); // [APPLE, APRICOT]
重要なポイント:遅延実行(Lazy Evaluation)¶
中間操作は、終端操作が呼ばれるまで**一切実行されません**。これにより、例えば「100万件のデータから、条件に合うものを3つ見つけたら終了する」といった最適化が自動で行われます。
次のステップ:難易度アップ問題¶
この基本を理解した上で、**「Stream APIの応用問題(少し難易度高め)」**を作成してもよろしいでしょうか?(例えば、flatMap の使い方や、複雑な Collectors を使ったグループ化などの問題です)