Javaを最初に勉強したとき、繰り返し処理といえばまずこの形を習った。
for (int i = 0; i < projects.size(); i++) {
Project project = projects.get(i);
System.out.println(project.getName());
}
一方、実務やAIが生成するコードでは、こちらの形をよく見る。
for (Project project : projects) {
System.out.println(project.getName());
}
自分が最初に習ったfor文とは見た目がかなり違う。
今回は、通常のfor文と拡張for文が何をしているのか、どんな場面で使い分けるのかを整理する。
最初に習ったfor文
まずは通常のfor文。
for (int i = 0; i < projects.size(); i++) {
Project project = projects.get(i);
System.out.println(project.getName());
}
1つずつ見る。
int i = 0
i を0から開始する。
i < projects.size()
i がListの要素数より小さい間、処理を繰り返す。
i++
1回処理するたびに i を1増やす。
projects.get(i)
i 番目の要素を取得する。
つまり、
0番目
↓
1番目
↓
2番目
↓
...
と、位置を自分で管理しながらListを処理している。
最近よく見る拡張for文
次の書き方は拡張for文と呼ばれる。
for (Project project : projects) {
System.out.println(project.getName());
}
この部分、
for (Project project : projects)
は、
projectsの中から
Projectを1件ずつ取り出して
projectに入れる
という意味。
通常のfor文のように、
int i = 0
や、
projects.get(i)
を書く必要がない。
同じ処理を並べる
通常のfor文。
for (int i = 0; i < projects.size(); i++) {
Project project = projects.get(i);
System.out.println(project.getName());
}
拡張for文。
for (Project project : projects) {
System.out.println(project.getName());
}
どちらも、
projectsの中にあるProjectを
順番に取り出して処理する
という点では同じ。
単純に全件を処理するだけなら、拡張for文の方が「何をしたいのか」が見えやすい。
実務でも拡張for文をよく使っていた
実務では、DBから取得したListを1件ずつ処理する場面でよく見かけた。
たとえば、
for (SourceEntity source : sourceList) {
TargetEntity target = new TargetEntity(
source.getId(),
source.getName(),
source.getStatus()
);
targetList.add(target);
}
これは、
sourceListから1件取り出す
↓
getterで値を取得する
↓
TargetEntityを作る
↓
targetListへ追加する
という処理。
こういった形は、実務でもかなり見慣れていた。
通常のfor文が向いている場合
拡張for文があれば通常のfor文が不要になるわけではない。
たとえば、何番目のデータなのかを使いたい場合。
for (int i = 0; i < projects.size(); i++) {
System.out.println(
(i + 1) + "件目:" + projects.get(i).getName()
);
}
逆順で処理したい場合も、
for (int i = projects.size() - 1; i >= 0; i--) {
System.out.println(projects.get(i).getName());
}
と書ける。
つまり、
インデックスを使いたい
順番を細かく制御したい
逆順に処理したい
場合は通常のfor文が分かりやすい。
拡張for文が向いている場合
一方、
for (Project project : projects) {
System.out.println(project.getName());
}
のように、
Listの中身を
最初から最後まで順番に処理する
だけなら拡張for文が自然。
インデックスではなく、
今処理しているProject
そのものに集中できる。
AIを使うようになってからよく見るようになった
自分がJavaを最初に習ったときは、
for (int i = 0; i < list.size(); i++)
という形から入った。
そのため、AIが生成するコードで、
for (Project project : projects)
を見る機会が増えて、
「最近はこちらの書き方が主流なのかな」
と感じた。
ただ、拡張for文自体は最近登場したものではない。
AIによって新しい書き方が生まれたというより、
自分が普段使っていなかった
一般的なJavaの書き方を見る機会が増えた
という方が近い。
まとめ
自分の中ではこう整理した。
通常のfor文
→ インデックスを自分で管理する
拡張for文
→ Listから要素を1件ずつ直接受け取る
通常のfor文は、
何番目かを使いたい
順番を制御したい
場合に向いている。
拡張for文は、
Listの中身を
1件ずつ順番に処理したい
場合に向いている。
どちらが新しい、古いというより、処理の目的によって使い分けるものだった。
そして、自分が実務でよく見ていた、
for (SourceEntity source : sourceList) {
TargetEntity target = new TargetEntity(...);
targetList.add(target);
}
という処理は、Streamの map と対応づけるとさらに理解しやすかった。
その部分は次の記事で整理する。