ではここでは、
「二重 for 文(ネスト)」を Stream API に置き換える実務例
を、初心者にもわかるように図+コード+実務パターンで解説します。
1. 基本構造の違いを図で理解しよう
● for文の処理の流れ(手動でループ)
for(要素A in listA) {
for(要素B in listB) {
処理(要素A, 要素B);
}
}
Java● Stream版の処理の流れ(宣言的)
listA.stream()
.flatMap(a -> listB.stream().map(b -> 処理(a, b)))
.forEach(...);
Java👉 flatMap() を使うと、「入れ子のループ」を「1本のストリーム」に変換できます。
2. 実務例①:商品 × クーポンの全組合せを作る
for文版
List<String> products = List.of("りんご", "バナナ");
List<String> coupons = List.of("10%OFF", "送料無料");
List<String> combos = new ArrayList<>();
for (String p : products) {
for (String c : coupons) {
combos.add(p + " × " + c);
}
}
combos.forEach(System.out::println);
Java🖥 出力:
りんご × 10%OFF
りんご × 送料無料
バナナ × 10%OFF
バナナ × 送料無料
Stream API版
List<String> combos = products.stream()
.flatMap(p -> coupons.stream().map(c -> p + " × " + c))
.toList();
combos.forEach(System.out::println);
Java📘 ポイント
flatMapは「ループの展開」mapの中で「内側ループ」を表現toList()で最終結果を収集
実務例②:2つの社員リストから「勤務地が同じペア」を抽出
for文版
for (Employee e1 : employeesA) {
for (Employee e2 : employeesB) {
if (e1.getOffice().equals(e2.getOffice())) {
System.out.println(e1.getName() + " と " + e2.getName() + " は同じ勤務地");
}
}
}
JavaStream版(filter+flatMap)
employeesA.stream()
.flatMap(e1 ->
employeesB.stream()
.filter(e2 -> e1.getOffice().equals(e2.getOffice()))
.map(e2 -> e1.getName() + " と " + e2.getName() + " は同じ勤務地"))
.forEach(System.out::println);
Java📘 ポイント
flatMapで「入れ子構造」を展開filterで条件を指定mapで出力文を組み立てる
実務例③:二次元リスト(表データ)の出力
for文版
List<List<String>> table = List.of(
List.of("山田", "営業", "東京"),
List.of("佐藤", "開発", "大阪"),
List.of("田中", "総務", "名古屋")
);
for (List<String> row : table) {
for (String col : row) {
System.out.print(col + "\t");
}
System.out.println();
}
JavaStream版
table.stream()
.map(row -> row.stream().collect(Collectors.joining("\t")))
.forEach(System.out::println);
Java📘 ポイント
map()の中で各行(List)を結合Collectors.joining("\t")で列を文字列化forEachで行ごとに出力
まとめ表(for文 → Stream変換チートシート)
| 処理目的 | for文構文 | Stream構文 | キー構文 |
|---|---|---|---|
| 全組合せ | 2重for | flatMap() | 展開 |
| 条件付き組合せ | 2重for+if | flatMap + filter | 条件 |
| 二次元データ出力 | ネストfor | map + joining | 整形 |
| ネストループを1本化 | – | flatMap() | flatten |
注意(実務の安全設計)
| 注意点 | 対策 |
|---|---|
| ループ中で例外発生 | try-catch を map 内で囲う |
| Streamで副作用が多い | peek() よりログ専用メソッドを使う |
| 大量データ | .parallelStream() 検討(要検証) |

