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

タイトル: 繰り返し制御文
SEOタイトル: Java 繰り返し制御文完全ガイド — for/while/拡張for

この記事の要点
  • Java の繰り返しは for / while / do-while / 拡張 for-each の 4 種
  • break でループ脱出、continue で次のイテレーションへ、ラベル付きで多重ループ脱出
  • 配列・コレクション走査は 拡張 for (for-each) が簡潔で安全
  • Stream API (Java 8+)forEach / map / filter で宣言的に書く
  • 無限ループfor (;;) または while (true)。break で抜ける設計

4 種類の繰り返し構文

// 1. for ループ (回数指定)
for (int i = 0; i < 10; i++) {
    System.out.println(i);
}

// 2. while ループ (条件指定)
int n = 0;
while (n < 10) {
    System.out.println(n);
    n++;
}

// 3. do-while ループ (最低 1 回実行)
int m = 0;
do {
    System.out.println(m);
    m++;
} while (m < 10);

// 4. 拡張 for-each (コレクション走査)
int[] arr = {10, 20, 30};
for (int v : arr) {
    System.out.println(v);
}

使い分けの目安

用途推奨構文理由
0 〜 N-1 回繰り返しfor (int i = 0; i < N; i++)定型で読みやすい
配列・List 全走査拡張 for / Stream添字管理不要、ミス減
条件が満たされる間while条件が主役のとき自然
最低 1 回は実行したいdo-while入力検証ループ等
Map のキー / 値走査拡張 for + entrySet()キー値同時取得が安全
並列処理 / 集約Stream API宣言的、並列化容易

for ループの細部

// 標準
for (int i = 0; i < 10; i++) { ... }

// 逆順
for (int i = 9; i >= 0; i--) { ... }

// 2 ずつ
for (int i = 0; i < 100; i += 2) { ... }

// 複数変数
for (int i = 0, j = 100; i < j; i++, j--) { ... }

// 無限ループ
for (;;) {
    if (condition) break;
}

// インデックス + 値 (List)
List list = List.of("a", "b", "c");
for (int i = 0; i < list.size(); i++) {
    System.out.println(i + ": " + list.get(i));
}

拡張 for-each (★ 推奨)

// 配列
String[] names = {"Taro", "Hanako", "Jiro"};
for (String name : names) {
    System.out.println(name);
}

// List
List nums = List.of(1, 2, 3);
for (int n : nums) {  // ★ Integer から int への自動 unboxing
    System.out.println(n);
}

// Map (entrySet が定番)
Map map = Map.of("a", 1, "b", 2);
for (Map.Entry e : map.entrySet()) {
    System.out.println(e.getKey() + " = " + e.getValue());
}

// キーだけ / 値だけ
for (String k : map.keySet())   { ... }
for (Integer v : map.values())  { ... }

拡張 for の制約:

  • インデックスを取れない (必要なら for ループへ)
  • 要素の追加・削除ができない (要 Iterator または別途リスト)
  • 要素の差し替えはできない (基本型では参照のコピーになる)

break / continue

// break: ループを完全に脱出
for (int i = 0; i < 100; i++) {
    if (i == 10) break;
    System.out.println(i);
}
// → 0..9 を出力

// continue: 次のイテレーションへスキップ
for (int i = 0; i < 10; i++) {
    if (i % 2 == 0) continue;
    System.out.println(i);  // 奇数だけ
}

// ラベル付き break / continue (多重ループ脱出)
outer:
for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
        if (i * j > 6) {
            break outer;  // 外側のループも抜ける
        }
        System.out.println(i + "," + j);
    }
}

Iterator パターン (要素削除)

List list = new ArrayList<>(List.of(1, 2, 3, 4, 5));

// ❌ 拡張 for 内で削除 → ConcurrentModificationException
for (Integer n : list) {
    if (n % 2 == 0) list.remove(n);   // ★ NG
}

// ✅ Iterator で削除
Iterator it = list.iterator();
while (it.hasNext()) {
    int n = it.next();
    if (n % 2 == 0) it.remove();
}

// ✅ Java 8+ removeIf (一番簡潔)
list.removeIf(n -> n % 2 == 0);

Stream API での代替 (Java 8+)

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

// 各要素に処理
nums.forEach(n -> System.out.println(n));
nums.forEach(System.out::println);  // メソッド参照

// 変換 + フィルタ + 集約
int sumOfSquaresOfEven = nums.stream()
    .filter(n -> n % 2 == 0)
    .mapToInt(n -> n * n)
    .sum();   // 4 + 16 = 20

// インデックス付きで処理 (IntStream)
String[] arr = {"a", "b", "c"};
IntStream.range(0, arr.length)
    .forEach(i -> System.out.println(i + ": " + arr[i]));

// 並列処理 (要素間で副作用が無い場合のみ)
nums.parallelStream().forEach(System.out::println);

ループのパフォーマンス Tips

  • サイズ取得をループ外に: int n = list.size(); for (int i = 0; i < n; i++)
  • 配列より ArrayList は微妙に遅い。クリティカルな計算ループは配列で
  • LinkedList の get(i) は O(n)。インデックスループでは ArrayList を使う
  • 文字列連結は StringBuilderString += は毎回新規 String 生成
  • Stream の forEach は for より若干遅い。ホットループでは for を選ぶ

無限ループのパターン

// イベント駆動
while (true) {
    Event e = queue.poll();
    if (e == null) {
        Thread.sleep(100);
        continue;
    }
    if (e.isStop()) break;
    process(e);
}

// 再試行
int retry = 0;
while (true) {
    try {
        return api.call();
    } catch (IOException ex) {
        if (++retry >= 3) throw ex;
        Thread.sleep(1000 * retry);
    }
}

FAQ

Q: do-while の用途は?
A: 最低 1 回は実行したいループ。ユーザー入力検証 (「正しい入力が来るまで聞く」) や再試行ループに自然です。

Q: 拡張 for と Stream forEach どちらを使うべき?
A: 単純な走査は拡張 for で十分。filter / map / reduce 等で集約するなら Stream。並列化したいなら parallelStream

Q: ループの中で配列を変更してもよい?
A: for (int v : arr) 内で arr[i] 書き換えは可だが、List の構造変更 (add/remove) は ConcurrentModificationException。Iterator か removeIf を使う。