この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:3
ページ更新者:atom
更新日時:2026-06-11 07:07:02

タイトル: ループ処理
SEOタイトル: Java ループ処理完全ガイド(for / while / 拡張 for / Stream)

この記事の要点
  • Java のループ構文for / while / do-while / 拡張 for (for-each) の 4 種
  • break でループ脱出、continue で次イテレーションへ。ラベル付き break で多重ループを一気に抜けられる
  • Collection は拡張 for が読みやすい。List xs; なら for (String x : xs) {...}
  • Stream API: list.stream().filter(...).forEach(...)。関数型スタイルで宣言的に書ける
  • ConcurrentModificationException: 拡張 for 中に Collection を変更すると発生 → Iterator.remove()removeIf()

4 種のループ構文

// 1. 古典 for: 初期化 / 条件 / 更新
for (int i = 0; i < 10; i++) {
    System.out.println(i);
}

// 2. while: 条件チェック → 実行
int i = 0;
while (i < 10) {
    System.out.println(i);
    i++;
}

// 3. do-while: 実行 → 条件チェック(最低 1 回実行)
int j = 0;
do {
    System.out.println(j);
    j++;
} while (j < 10);

// 4. 拡張 for (for-each): Collection / 配列
List names = List.of("taro", "jiro", "saburo");
for (String name : names) {
    System.out.println(name);
}

int[] nums = {1, 2, 3};
for (int n : nums) {
    System.out.println(n);
}

break と continue

for (int i = 0; i < 10; i++) {
    if (i == 3) continue;     // 3 だけスキップ
    if (i == 7) break;        // 7 で脱出
    System.out.println(i);
}
// 0, 1, 2, 4, 5, 6

// 無限ループ + break
while (true) {
    String input = scanner.nextLine();
    if (input.equals("quit")) break;
    process(input);
}

ラベル付き break / continue(多重ループ脱出)

outer:
for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
        if (matrix[i][j] == TARGET) {
            System.out.println("Found at " + i + "," + j);
            break outer;     // ★ 外側ループも抜ける
        }
    }
}

// continue にも使える
outer:
for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
        if (skip(i, j)) continue outer;  // 外側の次の i へ
        process(i, j);
    }
}

Stream API による関数型ループ

import java.util.stream.*;
import java.util.List;

List nums = List.of(1, 2, 3, 4, 5);

// forEach: 拡張 for 相当
nums.stream().forEach(System.out::println);
nums.forEach(System.out::println);   // Collection 直接 forEach も可

// filter + map + collect
List doubled = nums.stream()
    .filter(n -> n % 2 == 0)         // 偶数のみ
    .map(n -> n * 2)                 // 2 倍
    .collect(Collectors.toList());
// [4, 8]

// IntStream.range: インデックスベースループ
IntStream.range(0, 10).forEach(i -> System.out.println(i));
// 0, 1, 2, ..., 9

IntStream.rangeClosed(1, 10).sum();  // 1+2+...+10 = 55

// 並列実行(CPU 集約処理向け)
nums.parallelStream()
    .map(this::heavyCompute)
    .forEach(System.out::println);

Iterator による明示的ループ

List list = new ArrayList<>(List.of("a", "b", "c"));

Iterator it = list.iterator();
while (it.hasNext()) {
    String s = it.next();
    if (s.equals("b")) {
        it.remove();          // ★ ループ中の安全な削除
    }
}
System.out.println(list);     // [a, c]

ConcurrentModificationException 回避

拡張 for ループ中に Collection を変更すると、次のイテレーションで例外が出ます。

List list = new ArrayList<>(List.of("a", "b", "c"));

// ❌ ConcurrentModificationException
for (String s : list) {
    if (s.equals("b")) {
        list.remove(s);
    }
}

// ✅ 方法 A: Iterator.remove()
Iterator it = list.iterator();
while (it.hasNext()) {
    if (it.next().equals("b")) it.remove();
}

// ✅ 方法 B: removeIf() (Java 8+)
list.removeIf(s -> s.equals("b"));

// ✅ 方法 C: Stream で新しいリスト生成
list = list.stream()
    .filter(s -> !s.equals("b"))
    .collect(Collectors.toList());

性能比較: for vs 拡張 for vs Stream

方法速度可読性用途
古典 for(インデックス)最速(プリミティブ配列)性能クリティカル / インデックス必要
拡張 for高速★ 通常はこれ
Stream.forEachやや遅い(オートボックシング)関数型 / パイプライン
parallelStream大量データで速いCPU 集約 / 副作用なし
Iterator拡張 for と同等削除を伴うループ

無限ループの書き方

// while(true)
while (true) {
    if (shouldStop()) break;
    process();
}

// for(;;)
for (;;) {
    if (shouldStop()) break;
    process();
}

// do-while(true)
do {
    process();
} while (!shouldStop());

Map のループ

Map ages = Map.of("taro", 30, "jiro", 25);

// entrySet: キーと値両方
for (Map.Entry e : ages.entrySet()) {
    System.out.println(e.getKey() + ": " + e.getValue());
}

// keySet / values
for (String k : ages.keySet()) { ... }
for (Integer v : ages.values()) { ... }

// forEach (Java 8+)
ages.forEach((k, v) -> System.out.println(k + ": " + v));

FAQ

Q: 拡張 for でインデックスが欲しい
A: 拡張 for では取れません。古典 for を使うか、IntStream.range(0, list.size()).forEach(i -> ...)

Q: Stream.forEach と List.forEach、どちらが速い?
A: ほぼ同じ。Stream は遅延評価が効くパイプライン全体で考えるべきで、単独 forEach は List.forEach や拡張 for を推奨。

Q: parallelStream は常に速い?
A: いいえ。スレッド管理オーバーヘッドがあるため、要素数が少ない / 処理が軽いと逆に遅くなります。