Javaの拡張for文(for-each)とは?配列・コレクションの繰り返しを初心者向けに地方フルリモートエンジニアが実務視点で解説

Java基礎

配列やコレクションの要素を順番に処理するとき、インデックスを使わずにシンプルに書ける方法があります。それが「拡張for文(for-each文)」です。この記事では、Javaの拡張for文の書き方から通常のfor文との使い分け、さらに実務でよく使われるリストの扱い方まで、初心者の方にもわかりやすく解説します。

生徒
拡張for文って普通のfor文と何が違うんですか?
先生
拡張for文はインデックス(番号)を使わずに、配列やリストの要素を1つずつ取り出せるんだ。コードが短くて読みやすくなるよ!

拡張for文とは何か?初心者が知っておくべき基本概念

拡張for文(for-each文)とは、配列やコレクションの要素を順番に取り出して処理するための構文です。Java 5で導入されました。通常のfor文と比べて、インデックス変数を書く必要がなく、コードがシンプルで読みやすくなります。

拡張for文は、配列だけでなく、ListやSetなどのコレクションクラスでも使えます。実務では、配列よりもListやArrayListなどのコレクションを使うことが多く、拡張for文は非常に便利な構文です。

配列について詳しく知りたい方は、以下の記事も参考にしてください。

拡張for文の基本構文はどう書く?

for (データ型 変数名 : 配列またはコレクション) {
    // 変数を使った処理
}
読み方のコツ: 「配列の中の各要素について、その要素を変数に入れて処理する」と読むと理解しやすいです。英語では「for each element in array」なので「for-each文」とも呼ばれます。

通常のfor文との違いは何か?比較してみよう

for文について詳しく知りたい方は、以下の記事も参考にしてください。

通常のfor文

String[] fruits = {"りんご", "みかん", "ぶどう"};

// 通常のfor文(インデックスを使う)
for (int i = 0; i < fruits.length; i++) {
    System.out.println(fruits[i]);
}

拡張for文

String[] fruits = {"りんご", "みかん", "ぶどう"};

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

どちらも同じ結果:

りんご
みかん
ぶどう

拡張for文を使うと、インデックス変数iやlengthを書かなくて済むので、コードがシンプルになります。また、インデックスの範囲外アクセスやオフバイワンエラー(境界値の間違い)を防げるため、より安全なコードを書けます。

通常のfor文では、インデックスの範囲を間違えると、ArrayIndexOutOfBoundsExceptionが発生する可能性がありますが、拡張for文ではそのような心配がありません。配列やコレクションの全要素を順番に処理するだけの場合、拡張for文を使うことで、コードの可読性と安全性が向上します。

運営者
インデックスの範囲外エラーでバグを出した経験から、拡張for文を積極的に使うようになりました。
生徒
確かにシンプル!インデックスを書かなくていいんですね!

拡張for文の実践的な使用例

例1: 数値配列の合計を計算

public class EnhancedForSum {
    public static void main(String[] args) {
        int[] numbers = {10, 20, 30, 40, 50};
        int sum = 0;
        
        for (int num : numbers) {
            sum += num;
        }
        
        System.out.println("合計: " + sum);
    }
}

実行結果:

合計: 150

このコードでは、配列の全要素を順番に取り出して合計を計算しています。拡張for文を使うことで、シンプルに書けます。通常のfor文で書くと、`for (int i = 0; i < numbers.length; i++)`のようにインデックスを管理する必要がありますが、拡張for文では`for (int num : numbers)`と書くだけで、各要素を順番に取り出せます。

この例では、配列の各要素を変数`num`に代入し、それを`sum`に加算しています。インデックスを意識する必要がないため、コードが読みやすく、意図が明確になります。

例2: 最大値を求める

public class EnhancedForMax {
    public static void main(String[] args) {
        int[] scores = {85, 92, 78, 96, 88};
        int max = scores[0];  // 最初の要素を仮の最大値とする
        
        for (int score : scores) {
            if (score > max) {
                max = score;
            }
        }
        
        System.out.println("最高点: " + max);
    }
}

実行結果:

最高点: 96

このコードでは、配列の中から最大値を探しています。全要素を順番に比較する処理に拡張for文が適しています。最初の要素を仮の最大値として設定し、残りの要素を順番に比較していくことで、最大値を求めています。

この例では、配列の全要素を順番に取り出し、現在の最大値と比較しています。拡張for文を使うことで、インデックスを意識せずに、各要素にアクセスできます。通常のfor文で書くと、`if (scores[i] > max)`のようにインデックスを使う必要がありますが、拡張for文では`if (score > max)`と書くだけで済みます。

例3: 文字列の検索

public class EnhancedForSearch {
    public static void main(String[] args) {
        String[] names = {"田中", "鈴木", "佐藤", "山田"};
        String target = "佐藤";
        boolean found = false;
        
        for (String name : names) {
            if (name.equals(target)) {
                found = true;
                break;  // 見つかったらループを抜ける
            }
        }
        
        if (found) {
            System.out.println(target + "さんが見つかりました");
        } else {
            System.out.println(target + "さんは見つかりませんでした");
        }
    }
}

実行結果:

佐藤さんが見つかりました

このコードでは、配列の中から特定の文字列を検索しています。見つかったらbreakでループを抜けています。拡張for文でも、通常のfor文と同様に、break文を使ってループを途中で抜けることができます。

この例では、配列の各要素を順番にチェックし、目的の文字列が見つかったら`found`フラグを`true`に設定して、break文でループを抜けています。見つからなかった場合は、最後までループが実行され、`found`は`false`のままです。このように、拡張for文でも条件に応じてループを制御できます。

二次元配列での拡張for文の使い方

public class EnhancedFor2D {
    public static void main(String[] args) {
        int[][] matrix = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
        
        // 二次元配列をネストした拡張for文で処理
        for (int[] row : matrix) {
            for (int value : row) {
                System.out.print(value + " ");
            }
            System.out.println();
        }
    }
}

実行結果:

1 2 3 
4 5 6 
7 8 9

このコードでは、二次元配列をネストした拡張for文で処理しています。外側のループで行を取り出し、内側のループで各行の要素を取り出しています。二次元配列は、配列の配列として扱われるため、外側のループでは各行(1次元配列)が取り出され、内側のループでは各行の要素(数値)が取り出されます。

この例では、3行3列の二次元配列を処理しています。外側のループで各行を順番に取り出し、内側のループで各行の要素を順番に出力しています。通常のfor文で書くと、`matrix[i][j]`のように2つのインデックスを管理する必要がありますが、拡張for文では`row`と`value`という変数名で意図が明確になります。

注意!拡張for文が使えない場面とは?

拡張for文は便利ですが、使えない場面もあります。

使えない場面①: インデックスが必要な場合

String[] fruits = {"りんご", "みかん", "ぶどう"};

// 拡張for文ではインデックスを取得できない
for (String fruit : fruits) {
    // fruit は取れるが、「何番目」かは分からない
}

// インデックスが必要なら通常のfor文を使う
for (int i = 0; i < fruits.length; i++) {
    System.out.println((i + 1) + "番目: " + fruits[i]);
}

使えない場面②: 逆順に処理したい場合

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

// 拡張for文は必ず最初から順番に処理される

// 逆順なら通常のfor文を使う
for (int i = numbers.length - 1; i >= 0; i--) {
    System.out.println(numbers[i]);  // 5, 4, 3, 2, 1
}

使えない場面③: 要素を変更したい場合

NG: 要素が変更されない
int[] numbers = {1, 2, 3};

for (int num : numbers) {
    num = num * 2;  // これは配列の要素を変更しない!
}
// numbers は {1, 2, 3} のまま
OK: 通常のfor文を使う
int[] numbers = {1, 2, 3};

for (int i = 0; i < numbers.length; i++) {
    numbers[i] = numbers[i] * 2;  // 配列の要素を直接変更
}
// numbers は {2, 4, 6} になる
先生
拡張for文の変数は「コピー」だから、変更しても元の配列には反映されないんだ。要素を変更したい場合は通常のfor文を使おう!

実務ではリストを使うことが多い?拡張for文とコレクション

これまで配列での拡張for文の使い方を見てきましたが、実務では、配列よりも自作のクラスで定義したリストを使用してループするケースが多いです。Javaでは、ArrayListやLinkedListなどのコレクションクラスが頻繁に使われ、これらのコレクションに対して拡張for文を使うことで、コードがより読みやすくなります。

ArrayListを使った拡張for文の例

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

public class EnhancedForList {
    public static void main(String[] args) {
        // ArrayListを作成
        List fruits = new ArrayList<>();
        fruits.add("りんご");
        fruits.add("みかん");
        fruits.add("ぶどう");
        
        // 拡張for文でリストの要素を順番に処理
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
    }
}

実行結果:

りんご
みかん
ぶどう

このコードでは、ArrayListを使って文字列のリストを作成し、拡張for文で各要素を順番に出力しています。配列と同様に、インデックスを意識せずに各要素にアクセスできます。

自作クラスのリストを拡張for文で処理する例

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

// 自作クラス
class Student {
    private String name;
    private int score;
    
    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }
    
    public String getName() {
        return name;
    }
    
    public int getScore() {
        return score;
    }
}

public class EnhancedForCustomClass {
    public static void main(String[] args) {
        // 自作クラスのリストを作成
        List students = new ArrayList<>();
        students.add(new Student("田中", 85));
        students.add(new Student("鈴木", 92));
        students.add(new Student("佐藤", 78));
        
        // 拡張for文でリストの要素を順番に処理
        for (Student student : students) {
            System.out.println(student.getName() + ": " + student.getScore() + "点");
        }
    }
}

実行結果:

田中: 85点
鈴木: 92点
佐藤: 78点

このコードでは、自作クラス`Student`のリストを作成し、拡張for文で各要素を順番に処理しています。実務では、このように自作クラスのリストを扱うことが多く、拡張for文を使うことで、コードが読みやすくなります。

通常のfor文で書くと、`for (int i = 0; i < students.size(); i++)`のようにインデックスを管理する必要がありますが、拡張for文では`for (Student student : students)`と書くだけで、各要素にアクセスできます。また、`students.get(i)`のようにインデックスで要素を取得する必要がなく、直接`student`という変数名で要素にアクセスできるため、コードの意図が明確になります。

運営者
実務ではユーザー情報や商品情報のリストを扱うことが多いです。拡張for文なら動的なサイズ変更にも対応できます。

拡張for文と通常for文はどう使い分ける?

場面 拡張for文 通常for文
全要素を順番に処理 推奨
インデックスが必要 不可 推奨
逆順に処理 不可 推奨
要素を変更 不可 推奨
特定の範囲だけ処理 不可 推奨

まとめ

この記事では、Javaの拡張for文の基本から実践的な使い方、さらに実務でよく使われるリストの扱い方まで解説しました。拡張for文は、配列だけでなく、コレクションクラスや自作クラスのリストでも使える、非常に便利な構文です。

この記事のポイント

  • 拡張for文は「for (型 変数 : 配列)」で要素を取り出す
  • インデックスなしで全要素を処理できる
  • 読み取り専用の処理に最適
  • インデックス・逆順・変更が必要なら通常のfor文を使う
  • シンプルで可読性が高い
  • 実務では、配列よりも自作のクラスで定義したリストを使用してループするケースが多い
生徒
拡張for文、シンプルでいいですね!配列の全要素を処理するときに使ってみます!
先生
いいね!通常のfor文と使い分けられると、コードがもっと読みやすくなるよ。次はwhile文を学んでみよう!

while文について詳しく知りたい方は、以下の記事も参考にしてください。

拡張for文を使いこなして、シンプルで読みやすいコードを書けるようになりましょう!実務では、配列だけでなく、ArrayListや自作クラスのリストを扱うことが多いため、拡張for文の使い方を覚えておくと、コードの可読性と保守性が向上します。ぜひ活用していきましょう!