本ページはプロモーションが含まれています

Java入門

Java foreachの使い方|読み方と構文

トム

・都内自社開発企業勤務/Javaバックエンドエンジニア
/Java歴10年以上 ・首都圏在住30代
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎 詳細なプロフィール

Javaの拡張for文(foreach / フォーイーチ)は、配列やListの全要素を1行で処理できるループ構文です。

通常のfor文より短く書けて、インデックスミスによるバグも防げます。

この記事では拡張for文の読み方・基本構文から、配列・List・Mapでの実践コード、break/continueの使い方、ループ中に要素を削除する際の注意点まで網羅的に解説します。

Java 8のforEachメソッドとの違いも触れるので、現場で迷わず使い分けられるようになります。

  • 拡張for文(foreach)の読み方と基本構文がわかる
  • 通常のfor文・Java 8 forEachメソッドとの違いが理解できる
  • 配列・List・Mapでの実践的な使い方が身につく
  • ConcurrentModificationExceptionなど落とし穴の回避法がわかる

筆者はJava歴10年以上ですが、業務コードの90%以上で拡張for文を使っています。forEachメソッドはStream処理の流れで使う程度です。

この記事では、その判断基準も含めて実務目線で解説します。

拡張for文(foreach)とは?

Java拡張for文(foreach)とは何かを示す図解

Javaの拡張for文は、Java 5(2004年)で導入された、配列やコレクション(ListやSetなど)の全要素に対して順番に処理を繰り返すシンプルな構文です。2026年現在もJava 21 LTSを含む全バージョンで利用可能です。多くのプログラミング言語で「foreach」ループと呼ばれる機能と同じ役割を果たします。

この構文を使う最大のメリットは、コードが非常に簡潔になり、バグが起こりにくくなる点です。

拡張for文の基本構文と読み方

拡張for文の読み方は「フォーイーチ(for-each)」です。

英語圏のドキュメントでは "enhanced for loop" や "for-each loop" と表記されます。

日本語では「拡張for文」が正式名称ですが、現場では単に「foreach」と呼ぶのが一般的です。

構文は驚くほどシンプルです。

for (型 変数名 : 配列またはコレクション) {
    // 各要素に対する処理
}

このように書きます。読み方は「配列またはコレクションの各要素を、順番に取り出して変数に入れ、中の処理を繰り返す」と理解すると分かりやすいです。

例えば、String型の配列namesがあり、その要素を1つずつ画面に表示したい場合、以下のように書けます。

String[] names = {"Alice", "Bob", "Charlie"};

for (String name : names) {
    System.out.println(name);
}

このコードは、names配列から要素を1つずつ取り出し、nameという変数に代入して、printlnで表示する処理を繰り返します。

Java 10以降では、varキーワードで型宣言を省略することもできます。

// Java 10以降: varで型推論
var names = List.of("Alice", "Bob", "Charlie");
for (var name : names) {
    System.out.println(name);
}

型が明らかな場合はvarを使うとコードがさらに簡潔になります。ただし、チームの規約で禁止されている場合もあるので確認しましょう。

通常のfor文との違い

従来のfor文と比較すると、その違いは一目瞭然です。同じ処理を通常のfor文で書くと、以下のようになります。

String[] names = {"Alice", "Bob", "Charlie"};

for (int i = 0; i < names.length; i++) {
    String name = names[i];
    System.out.println(name);
}

拡張for文と比べると、カウンタ変数iの初期化、条件式、更新処理が必要で、記述量が多くなります。

特に、i < names.lengthのような条件式や、names[i]といったインデックスを使った要素の取得は、タイプミスによるバグ(例えば<=にしてしまいArrayIndexOutOfBoundsExceptionが発生するなど)の原因になりがちです。

拡張for文なら、インデックスを意識する必要がないため、そのような心配がなく、より安全にコードを書けるのです。

「foreach」と呼ばれる理由

Javaの公式ドキュメント(JLS)では "Enhanced For Statement"(拡張for文)と定義されています。

しかし現場では「foreach(フォーイーチ)」と呼ぶのが圧倒的に一般的です。

その理由は、C#のforeach、PHPのforeach、JavaScriptのfor...ofなど、他言語に同名・同機能のループ構文が存在するためです。

Javaにはキーワードとしてのforeachはありませんが、機能的に同じ役割を果たすため「for-eachループ」「foreachループ」と呼ばれています。

拡張for文の使い方【基本編】

Java foreachの基本的な使い方を示す図解

具体的な使い方をデータ構造ごとに見ていきましょう。

配列に対して使う方法

最も基本的な使い方が、配列に対するループ処理です。先ほどの例でも使いましたが、int型の配列でも同様に扱えます。

// int型の配列を準備
int[] scores = {90, 85, 70, 95, 80};

// 合計点を計算する変数を準備
int sum = 0;

// 拡張for文で配列の各要素を足し合わせる
for (int score : scores) {
    sum += score;
}

System.out.println("合計点: " + sum); // 出力結果: 合計点: 420

配列の全要素に対して何らかの処理を行いたい場合に非常に有効です。

List(ArrayList)をforeachで処理する方法

Javaでは、ArrayListHashSetなど、コレクションフレームワークのクラスを頻繁に使います。

拡張for文は、これらのコレクションに対しても全く同じように使えます。

ArrayListの例を見てみましょう。

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Orange");

        // Listの要素を拡張for文で取り出す
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
    }
}

この拡張for文が使えるのは、ArrayListIterableインターフェースを実装しているからです。

java.lang.Iterableを実装しているクラスであれば、どんなものでも拡張for文の対象にできます。

なお、Java 9以降ではList.of("Apple", "Banana", "Orange")で不変リストを簡潔に作成でき、拡張for文でそのまま使えます。

foreachでインデックス(index)を取得する方法

拡張for文の大きな特徴は、インデックスを使わない手軽さです。

しかし、処理によっては「今、何番目の要素を処理しているか」というインデックス番号が必要になる場面もあります。

結論から言うと、拡張for文では直接インデックスを取得できません。

どうしてもインデックスが必要な場合は、2つの対処法があります。

外部にカウンタ変数を置く

List<String> languages = new ArrayList<>();
languages.add("Java");
languages.add("Python");
languages.add("Go");

int index = 0;
for (String lang : languages) {
    System.out.println(index + ": " + lang);
    index++;
}

このようにループの外でカウンタ変数を宣言し、ループ内でインクリメント(+1)する方法です。ただし、この方法は少し冗長に見えます。

通常のfor文を使う

インデックスを使った処理がメインの場合は、無理に拡張for文を使わず、素直に通常のfor文を使った方がコードがシンプルで分かりやすくなります。

for (int i = 0; i < languages.size(); i++) {
    System.out.println(i + ": " + languages.get(i));
}

適材適所で構文を使い分けるのが、良いプログラマーのスキルです。

拡張for文の使い方【応用編】

Java foreachの応用的な使い方を示す図解

配列やList以外のデータ構造での使い方を見ていきましょう。

ネストされた配列・リストを処理する

二次元配列や、リストの中にリストが入っているような、ネスト(入れ子)構造のデータも、拡張for文をネストさせることで簡単に処理できます。

例えば、二次元配列(九九の表のようなもの)を考えてみましょう。

int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

// 拡張for文をネストさせる
for (int[] row : matrix) { // まず外側の配列から内側の配列(行)を取り出す
    for (int num : row) { // 次に内側の配列から各要素を取り出す
        System.out.print(num + " ");
    }
    System.out.println(); // 行ごとに改行
}

出力結果:

1 2 3 
4 5 6 
7 8 9 

外側のループで各行(int[] row)を取り出し、内側のループでその行の各要素(int num)を取り出しています。

このように構造が直感的に分かりやすいのが利点です。

Mapをforeachで処理する3つの方法

MapIterableを実装していないため直接foreachに渡せませんが、以下の3つのメソッドでキーや値を取得すれば拡張for文で処理できます。

keySet()

キーの一覧(Set)を取得します。キーだけが必要な場合に使います。

Map<String, Integer> items = new HashMap<>();
items.put("Pen", 100);
items.put("Notebook", 150);
for (String key : items.keySet()) {
    System.out.println("キー: " + key);
}

values()

値の一覧(Collection)を取得します。値だけが必要な場合に使います。

for (Integer value : items.values()) {
    System.out.println("値: " + value);
}

entrySet()

キーと値のペア(Map.Entry)の一覧を取得します。両方を同時に使う場合はこのentrySet()が定石です。

for (Map.Entry<String, Integer> entry : items.entrySet()) {
    String key = entry.getKey();
    Integer value = entry.getValue();
    System.out.println(key + " は " + value + "円です。");
}

foreachでbreak・continueを使う方法

拡張for文の中でも、通常のfor文と同じようにbreakcontinueが使えます。

  • break: ループ処理を完全に中断します。
  • continue: 現在の周の処理をスキップし、次の要素の処理に移ります。

breakの例: 配列の中から特定の数値を見つけたら処理を終了する

int[] numbers = {1, 5, -3, 8, 4};

for (int num : numbers) {
    if (num < 0) {
        System.out.println("負の数を見つけたので処理を中断します。");
        break;
    }
    System.out.println("処理した数値: " + num);
}

continueの例: 偶数だけを処理対象とする(奇数はスキップする)

for (int num : numbers) {
    if (num % 2 != 0) { // 奇数の場合はスキップ
        continue;
    }
    System.out.println("処理した偶数: " + num);
}

拡張for文の注意点と落とし穴

Java foreachの注意点を示す図解

非常に便利な拡張for文ですが、いくつか知っておくべき注意点があります。これを知らないと、予期せぬエラーの原因となる可能性があります。

筆者が実務のコードレビューでよく指摘する「拡張for文のやりがちミス」を3つ紹介します。

  1. ループ内でリストに追加してしまう: list.add()をループ内で呼ぶとConcurrentModificationException。別リストに溜めてループ後にaddAll()で解決。
  2. nullチェックを忘れる: 外部APIの戻り値がnullの場合、そのままforeachに渡すとNullPointerException。メソッド冒頭で空リスト化するのが定石。
  3. 要素を直接書き換えようとする: item = newValueとしてもループ変数が変わるだけで元のリストは不変。フィールドの書き換え(item.setName(...))はOKだが、要素そのものの差し替えには通常for文を使う。

それぞれの詳細を以下で解説します。

要素の削除や変更ができない理由

最も重要な注意点は、拡張for文のループ内で、ループ対象のコレクションの要素を追加したり削除したりしてはいけないというルールです。

もし実行すると、ConcurrentModificationExceptionという例外が発生します。

List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");

// これはエラーになる!
for (String str : list) {
    if ("B".equals(str)) {
        list.remove(str); // ループ中に要素を削除しようとしている
    }
}

なぜエラーになるのでしょうか。その理由は、拡張for文の内部的な仕組みにあります。

拡張for文は、コンパイルされるとIterator(イテレータ)という仕組みを使ったコードに変換されます。

Iteratorは、コレクションの状態(要素数など)を記憶しながら要素を1つずつ取り出します。

ループの途中で元のコレクションが変更されると、Iteratorが記憶している状態と食い違いが生じ、安全に処理を続けられないため、例外を発生させて処理を止めるのです。

これをフェイルファスト(fail-fast)と呼びます。

Iteratorとの違いを理解しよう

では、ループ中に要素を安全に削除したい場合はどうすればよいのでしょうか。

その答えは、拡張for文の内部で使われているIteratorを明示的に使うことです。

Iteratorにはremove()というメソッドがあり、これを使えば安全に要素を削除できます。

List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");

Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String str = iterator.next();
    if ("B".equals(str)) {
        iterator.remove(); // Iteratorのremove()メソッドを使う
    }
}

System.out.println(list); // 出力結果: [A, C]

少し記述は増えますが、ループ中の安全な要素削除にはIteratorを使う、と覚えておきましょう。

nullの配列・Listに注意(NullPointerException対策)

拡張for文にnullの配列やコレクションを渡すと、NullPointerExceptionが発生します。

List<String> list = null;

// NullPointerExceptionが発生する!
for (String item : list) {
    System.out.println(item);
}

対策として、ループの前にnullチェックを入れるか、空のコレクションで初期化しましょう。

// 方法1: nullチェック
if (list != null) {
    for (String item : list) {
        System.out.println(item);
    }
}

// 方法2: Optional + orElseで空リスト化
for (String item : Optional.ofNullable(list).orElse(List.of())) {
    System.out.println(item);
}

拡張for文を使うべきケース・使わない方がよいケース

Java foreachの活用ケースを示す図解

実務でどのループ構文を使うか迷ったとき、以下の判断表を参考にしてください。

やりたいことおすすめ構文理由
全要素を順に読み取る拡張for文最もシンプルで安全
途中でbreakしたい拡張for文forEachではbreak不可
インデックスが必要通常for文拡張for文ではindex取得不可
要素を削除したいIterator / removeIfConcurrentModificationException回避
1行で簡潔に書きたいforEachメソッドラムダ式で最短記述
並列処理したいparallelStream().forEach()マルチスレッド対応

読み取り専用の処理に最適

拡張for文が最も輝くのは、配列やコレクションの全要素に対して、順番に参照するだけの処理です。

  • 全要素を画面に表示する
  • 全要素の合計値や平均値を計算する
  • 特定の条件に合う要素を探す

このようなケースでは、コードが簡潔で読みやすくなり、インデックスの指定ミスといったバグも防げるため、積極的に使うべきです。

ループ中に要素を変更する場合は避ける

一方で、以下のようなケースでは拡張for文は不向きです。通常のfor文やIteratorを使いましょう。

  • ループ中に要素の追加や削除を行いたい場合→ Iteratorを使いましょう。
  • 特定のインデックスの要素を直接書き換えたい場合→ 通常のfor文を使いましょう。(例:array[i] = newValue;)
  • 逆の順番で(末尾から先頭へ)処理したい場合→ 通常のfor文でカウンタをデクリメント(-1)させましょう。
  • 処理中にインデックス番号そのものが必要な場合→ 通常のfor文を使いましょう。

拡張for文とJava 8 forEachメソッドの違い

Java 8(2014年)以降では、コレクションのforEachメソッドとラムダ式を組み合わせた書き方も使えます。

2026年現在、実務で最も多い選択肢は「拡張for文」と「forEachメソッド」の2つです。混同しやすいので、違いを整理しておきましょう。

List<String> names = List.of("Alice", "Bob", "Charlie");

// 拡張for文
for (String name : names) {
    System.out.println(name);
}

// Java 8 forEachメソッド
names.forEach(name -> System.out.println(name));

どちらも全要素を順に処理しますが、以下の違いがあります。

  • break/continue: 拡張for文では使えるが、forEachメソッド内のラムダ式では使えない(returnで1回分をスキップする形になる)
  • チェック例外: 拡張for文はtry-catchで囲めるが、forEachのラムダ内でチェック例外をスローできない
  • 可読性: 単純な1行処理ならforEachメソッドが簡潔。複数行の処理や条件分岐が多い場合は拡張for文のほうが読みやすい

実務では「breakが必要」「複雑な処理を書く」場合は拡張for文、「要素を1つずつ単純に処理するだけ」ならforEachメソッドと使い分けるのがおすすめです。

パフォーマンスの違い: 拡張for文とforEachメソッドの実行速度はほぼ同等です。

JMHベンチマークでは100万要素のListで差は1ms未満であり、速度を理由にどちらかを選ぶ必要はありません。可読性とチームの規約で選びましょう。

まとめ:拡張for文を使えばコードが読みやすくなる

この記事では、Javaの拡張for文(foreach)について、基本的な使い方から応用、そして注意点までを解説しました。

for-eachでミスを減らし、コードをシンプルにするためのポイントをまとめます。

  • 拡張for文(foreach)は、配列やコレクションの全要素を順番に処理するためのシンプルな構文です。
  • for (型 変数名 : コレクション) の形で使います。
  • 通常のfor文に比べてコードが短く、インデックス関連のバグを防げるのが大きなメリット。
  • ListSetはもちろん、MapentrySet()などを使えば処理可能です。
  • 最大の注意点は、ループ中にコレクションの要素を追加・削除できないこと。変更が必要な場合はIteratorを使いましょう。
  • Java 10以降はvarで型宣言を省略可能。Java 9以降はList.of()で不変リストを手軽に作成可能。

拡張for文は、Javaのコードをより安全で、誰にとっても読みやすいものにしてくれる強力なツールです。

適切に使いこなせば、あなたのプログラミングの効率と品質は間違いなく向上します。

Java拡張for文(foreach)に関するよくある質問

foreachの読み方は?

「フォーイーチ」と読みます。英語の「for each(それぞれについて)」に由来し、コレクションや配列の各要素に対して順番に処理を行うことを意味します。

拡張for文でインデックス(添字)は使えますか?

拡張for文自体にはインデックスの概念がなく、直接取得できません。インデックスが必要な場合は通常のfor文を使うか、Java 8以降であればストリームAPIのIntStream.range()と組み合わせる方法があります。

拡張for文とJava 8のforEachメソッドはどちらを使うべきですか?

単純な繰り返し処理なら可読性の高い拡張for文で十分です。ラムダ式でのメソッド参照や、ストリーム処理と組み合わせたい場合はforEachメソッドが向いています。break/continueを使いたい場合は拡張for文一択です(forEachメソッド内では使えません)。

  • この記事を書いた人
  • 最新記事

トム

・都内自社開発企業勤務/Javaバックエンドエンジニア
/Java歴10年以上 ・首都圏在住30代
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎 詳細なプロフィール

-Java入門