9.

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

編集
この記事の要点
  • Java のループ構文for / while / do-while / 拡張 for (for-each) の 4 種
  • break でループ脱出、continue で次イテレーションへ。ラベル付き break で多重ループを一気に抜けられる
  • Collection は拡張 for が読みやすい。List<String> 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<String> 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<Integer> 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<Integer> 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<String> list = new ArrayList<>(List.of("a", "b", "c"));

Iterator<String> 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<String> list = new ArrayList<>(List.of("a", "b", "c"));

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

// ✅ 方法 A: Iterator.remove()
Iterator<String> 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<String, Integer> ages = Map.of("taro", 30, "jiro", 25);

// entrySet: キーと値両方
for (Map.Entry<String, Integer> 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: いいえ。スレッド管理オーバーヘッドがあるため、要素数が少ない / 処理が軽いと逆に遅くなります。

編集
Post Share
子ページ
  1. for文
同階層のページ
  1. 記述方法
  2. コメント
  3. 変数の宣言
  4. 関数
  5. 演算子
  6. 条件文
  7. 配列
  8. 連想配列
  9. ループ処理
  10. 非同期処理
  11. 同期処理
  12. 確認ウィンドウを表示する方法
  13. 文字の置換
  14. base urlを取得する方法
  15. formのsubmit前にjavascriptを呼び出す方法
  16. undefinedのイコール判定
  17. Javascript のみで form を post で submit する方法

最近更新/作成されたページ