はじめに
Java で配列やコレクションを扱うときに便利なのが
拡張 for 文(foreach)。
Java
for (String s : list) {
System.out.println(s);
}シンプルで読みやすい構文ですが、
実は できること・できないことがはっきりしている ため、
誤解して使うとバグにつながることもあります。
この記事では、やさしく・実務寄りに
拡張 for 文の特徴を整理していきます。
拡張 for 文で「できること」
① 配列・コレクションの全要素を順番に取り出す
Java
for (int n : numbers) {
System.out.println(n);
}- 配列
- List
- Set
- その他 Iterable
これらを 先頭から順に取り出す のが得意です。
② 読みやすいコードになる
従来の for 文よりスッキリします。
Java
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}↓
Java
for (String s : list) {
System.out.println(s);
}「要素を順番に処理する」意図が明確です。
③ null チェック不要で安全に走査できる
Java
for (String s : list) { ... }list が null でない限り、
内部で Iterator を使って安全に走査してくれます。
拡張 for 文で「できないこと」
① インデックス(i)を使った処理
Java
for (String s : list) {
// s は取れるが、i は取れない
}- 何番目の要素か知りたい
- 偶数番目だけ処理したい
- 前後の要素と比較したい
こうした処理は 従来の for 文 が必要です。
② 要素を削除・追加しながらループする
Java
for (String s : list) {
list.remove(s); // ← ConcurrentModificationException
}拡張 for 文は内部で Iterator を使っているため、
ループ中の構造変更は例外になります。
削除したい場合は Iterator を使う
Java
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if (条件) {
it.remove(); // 安全に削除できる
}
}③ 要素そのものを変更しても元のリストに反映されない
Java
for (String s : list) {
s = "changed"; // list の中身は変わらない
}拡張 for 文で取り出した変数は コピー です。
元のリストの要素は変更されません。
要素を更新したい場合はインデックスが必要
Java
for (int i = 0; i < list.size(); i++) {
list.set(i, "changed");
}④ 逆順での走査ができない
Java
for (String s : list) { ... } // 順方向のみ逆順で処理したい場合は:
- 従来の for 文
- ListIterator
- Stream API(Collections.reverse など)
を使います。
拡張 for 文のまとめ(できること・できないこと)
できること
- 全要素を順番に取り出す
- 読みやすいコードを書く
- 配列・コレクションを安全に走査する
できないこと
- インデックスを使う
- 要素を削除・追加する
- 要素の値を直接更新する
- 逆順で走査する
実務での使い分け
拡張 for 文が向いている場面
- 単純に全要素を処理したい
- 読みやすさを優先したい
- 削除・追加が不要
従来の for 文が向いている場面
- インデックスが必要
- 要素を更新したい
- 逆順で処理したい
- 削除・追加を行いたい
まとめ
拡張 for 文は「読みやすさ重視」の構文
- 配列・コレクションを順番に処理するのが得意
- インデックス操作や削除・追加は苦手
実務では「使い分け」が大切
- シンプルな処理 → 拡張 for 文
- 複雑な処理 → 従来の for 文 or Iterator

decopon
拡張 for 文は、 「読みやすさ」と「安全さ」を両立した素敵な構文です。ただし、できること・できないことを知っておくと 実務でのバグをぐっと減らせます。あなたの学びが、次のステップにつながりますように。

moco
foreach は“読むための for”。
インデックスや削除が必要なら、普通の for が向いてるよ。

コメント