はじめに
基本・配列・ネスト・制御まで来たら、次は
for文の器用な書き方をまとめて押さえよう。
初期化・条件・更新を工夫すると、コードがスッキリ書けたり、
1本のループで“二役”こなせるようになるよ。
🎓 ルール再確認:複数書けるのは初期化と更新
for (int i = 0, j = 10; i < j; i++, j--) {
// i は昇順、j は降順で中央に近づく
}
-
初期化と更新はカンマ区切りで複数OK。
-
条件は1つだけ。複数条件は
&&や||で繋ぐ:for (int i = 0, j = n - 1; i < j && i < 100; i++, j--) { ... }
⚡ 代表パターン集(そのまま使える)
1) 両端から中央に向かう走査(ツインカウンタ)
for (int left = 0, right = arr.length - 1; left < right; left++, right--) {
// arr[left] と arr[right] を同時に扱う(反転・比較など)
}
2) ステップを変える(2ずつ、3ずつ、等比的など)
for (int i = 0; i <= 20; i += 2) { /* 偶数のみ */ }
for (int i = 1; i <= 81; i *= 3) { /* 1,3,9,27,81 */ }
3) 逆順+スキップ(降順で2つ飛ばし)
for (int i = list.size() - 1; i >= 0; i -= 2) { /* 後ろから奇数番目だけ */ }
4) 更新を本体側で行う(可読性優先や条件分岐で増分が変わる)
int i = 0;
for (; i < n; ) {
System.out.println("処理対象: " + i);
i++; // 1つずつカウントアップ
}
🪄 設計ポイント(ここを外さない)
-
一貫性:開始値・終了条件・増分の「向き」を揃える(例:昇順なら
i = 0; i < n; i++)。 -
境界の明示:
<=ではなく<にできないかまず検討(範囲外アクセス防止)。 -
役割の分離:複数カウンタで可読性が落ちるなら、処理をメソッドに切り出す。
-
浮動小数は避ける:
for (double x = 0; x != 1.0; x += 0.1)は精度誤差で終了しないことがある。for (int k = 0; k <= 10; k++) { double x = k / 10.0; /* 0.0〜1.0 */ }
🐛 ありがちエラーと落とし穴
1. 条件は1つと忘れて i < j, j > 0 のように書いてコンパイルエラー
for (int i = 0, j = 10; i < j, j > 0; i++, j--) { } // NG: 条件にカンマは使えない
➡ 対策:i < j && j > 0 のように論理演算子で繋ぐ。
2. 向きの不一致でループが即終了/無限継続
for (int i = 10; i < 0; i++) { /* 条件に入らず0回 */ }
for (int i = 0; i < 10; i--) { /* 減っていくので無限ループに近い挙動 */ }
➡ 対策:開始・条件・更新の向きを点検。
3. 等比増加で条件を満たさず行き過ぎる
for (int x = 1; x == 100; x *= 4) { /* 1,4,16,64 → 256で抜けずに…? 条件次第で暴れる */ }
➡ 対策:終了条件を上限/下限で厳密に。必要なら break を併用。
4. カウンタの混在で読みづらい
for (int i = 0, j = 0; i < n; i++) {
j += i; /* jの役割が見えづらい */
}
➡ 対策:副作用のある更新は本体内に寄せ、名前で意味を明確に。
次回予告
次は for文の限界とその先。for(;;) の無限ループ、ラベル付きbreak/continue、そして stream().forEach() との使い分けをまとめていくよ!
ピッピカチュウ!!
あとがき
ここまで読んでくれて、本当にありがとうございました。
「プログラミングって難しい…」って思ってた人も、
「ちょっと楽しいかも…!」って思ってもらえたらうれしいな。
次の投稿も、よろしくおねがいします。
💬 コメント・フィードバック歓迎!
「この章わかりやすかった!」
「これ表現まちがってない?」
「次は○○をやってほしい!」などなど、
お気軽にコメントで教えてくださいね!