では、「拡張 for 文 vs Stream API の処理フロー横並び比較図」 を作ります。
これで どの処理がどこで行われているかを一目で理解できる教材 にします。
例題:社員リストから「年齢 ≥ 25 の社員を名前大文字化して、部署ごとにまとめる」
入力データ
class Employee {
String name;
String dept;
int age;
Employee(String n, String d, int a){ name=n; dept=d; age=a; }
}
List<Employee> employees = List.of(
new Employee("Alice","DeptA",30),
new Employee("Bob","DeptB",22),
new Employee("Charlie","DeptA",25),
new Employee("David","DeptB",28),
new Employee("Eve","DeptC",35)
);
Java1️⃣ 拡張 for 文版
Map<String, List<String>> deptMap = new HashMap<>();
for (Employee e : employees) {
if (e.age >= 25) { // filter
String name = e.name.toUpperCase(); // map
deptMap.computeIfAbsent(e.dept, k -> new ArrayList<>()).add(name); // groupingBy
}
}
System.out.println(deptMap);
Java処理フロー図
[入力リスト: employees]
Alice-30, Bob-22, Charlie-25, David-28, Eve-35
│
▼ (for ループ)
1件ずつ e を取り出す
│
▼ if (e.age >= 25) ? (filter)
Alice, Charlie, David, Eve が通過
│
▼ name.toUpperCase() (map)
ALICE, CHARLIE, DAVID, EVE
│
▼ deptMap に追加 (groupingBy)
DeptA -> [ALICE, CHARLIE]
DeptB -> [DAVID]
DeptC -> [EVE]
2️⃣ Stream API 版
Map<String, List<String>> deptMap = employees.stream()
.filter(e -> e.age >= 25) // filter
.map(e -> new Employee(e.name.toUpperCase(), e.dept, e.age)) // map
.collect(Collectors.groupingBy(
e -> e.dept,
Collectors.mapping(e -> e.name, Collectors.toList())
)); // groupingBy
Java処理フロー図
[入力リスト: employees]
Alice-30, Bob-22, Charlie-25, David-28, Eve-35
│
▼ stream() 開始
│
▼ filter() : 年齢 >= 25
ALICE-DeptA-30, CHARLIE-DeptA-25, DAVID-DeptB-28, EVE-DeptC-35
│
▼ map() : 名前大文字化
│
ALICE-DeptA-30, CHARLIE-DeptA-25, DAVID-DeptB-28, EVE-DeptC-35
│
▼ collect(groupingBy + mapping)
│
▼ 出力Map
DeptA -> [ALICE, CHARLIE]
DeptB -> [DAVID]
DeptC -> [EVE]
3️⃣ 横並び比較図(処理フロー対比)
拡張 for 文 Stream API
───────────────────────────────
for ループで1件ずつ取り出す stream()で流れを作る
│ │
▼ ▼
if (条件) で絞り込む filter()
│ │
▼ ▼
名前を大文字化 map()
│ │
▼ ▼
Map に追加して集計 collect(groupingBy + mapping)
│ │
▼ ▼
結果Map完成 結果Map完成
- 拡張 for 文:手続き的に「何をどうするか」を順に書く
- Stream API:宣言的に「何をしたいか」をメソッドチェーンで書く
- どちらも同じ結果だが、Stream API はパイプライン処理を直感的に表現できる
4️⃣ 実務での判断目安
| 観点 | 拡張 for 文 | Stream API |
|---|---|---|
| コード量 | やや多い | 少なく簡潔 |
| 複雑な加工 | if 条件 + Map操作 | filter → map → collect で直感的 |
| 可読性 | 小規模ループは読みやすい | パイプライン形式で意図が明確 |
| 拡張性 | 処理追加はループ内に追記 | メソッドチェーンで簡単に追加 |
| 並列化 | 自前で工夫が必要 | parallelStream() で容易 |
💡 ポイントまとめ
- 「何をしたいか」を重視 → Stream API
- 「順番に1件ずつ処理する」だけ → 拡張 for 文
- 両者の処理フローを図で対比すると、初心者でもどこで何をしているか一目で理解できる


