Java道|for文の入れ子構造と多重ループ

繰り返しの中に、さらに繰り返し。
for文のネストを覚えると、表や模様のような複雑な処理も、きれいに整理して書ける。

ここまでで、for文を使った基本的な繰り返し処理を学んできました。

for文を使うと、1回目、2回目、3回目のように回数を数えながら、同じ処理をくり返せます。
たとえば、メッセージを5回表示する、1から10まで順番に処理する、入力された回数だけ記号を表示するといった処理に向いていました。

ただ、プログラムを書いていると、単純な1方向の繰り返しだけでは足りない場面があります。

たとえば、表のように行と列を扱いたい場合です。
4行3列のマスを順番に確認したい。
4行6列の記号模様を作りたい。
縦方向と横方向を組み合わせて、すべての位置を処理したい。

このようなときに使うのが、for文のネストです。

ネストとは、ある文の中に別の文を入れ子のように組み込むことです。for文の中にさらにfor文を書くと、外側の繰り返しの1回ごとに、内側の繰り返しを最初から最後まで実行できます。このような繰り返しの構造を多重ループと呼びます。この記事では、指定内容に沿って Sample7.java と Sample8.java のみを使い、for文の入れ子構造、多重ループの動き、外側と内側の役割、if文との組み合わせまでを、鬼滅の刃風の世界観にたとえながら整理します。

鬼滅の刃風にたとえると、for文のネストは「大きな修行場の中で、行ごとに型を確認していく訓練」です。
外側のループは、修行場の行を進める役割です。
内側のループは、その行の中にある列を順番に確認する役割です。
1行目のすべての型を確認したら、2行目へ進む。
2行目でもまた、列を1つずつ確認する。
このように、外側と内側の役割を分けて考えると、多重ループはぐっと読みやすくなります。

ネストとは何か

ネストとは、文の中に別の文を入れ子にして書くことです。

for文の中にfor文を書くと、次のような形になります。

for(外側の初期化; 外側の条件式; 外側の変化式){
    for(内側の初期化; 内側の条件式; 内側の変化式){
        繰り返したい処理;
    }
}

↓クリックすると拡大表示されます。

このように書くと、外側のfor文が1回進むたびに、内側のfor文が最初から最後まで実行されます。

呼び方役割
外側のループ全体の大きな流れを管理する
内側のループ外側の1回ごとに細かい繰り返しを行う

ここで大切なのは、外側と内側を分けて考えることです。

外側のループは、大きなまとまりを進めます。
内側のループは、そのまとまりの中で細かく処理をくり返します。

鬼滅の刃風にたとえると、外側のループは「修行場の列に進む隊長」、内側のループは「その列の中で型を1つずつ確認する隊士」です。
隊長が1つの行を担当すると、その中の隊士がすべての型を確認します。
それが終わると、隊長は次の行へ進み、また内側の確認が始まります。

for文のネストの基本イメージ

for文のネストは、行と列を扱う場面で考えると分かりやすいです。

たとえば、次のような処理です。

やりたいこと外側と内側の考え方
表のマスを順番に処理する外側が行、内側が列
記号を縦横に並べる外側が行、内側が1行分の文字
座標を順番に確認する外側が縦位置、内側が横位置
すべての組み合わせを調べる外側と内側で2つの値を組み合わせる

たとえば、外側のループが4回、内側のループが3回動くとします。

この場合、全体の処理回数は次のようになります。

4 × 3 = 12回
外側の回数内側の回数合計の処理回数
4回3回12回

多重ループでは、この掛け算の感覚がとても大切です。

外側が1回進むたびに、内側が全部動きます。
そのため、全体の回数は、外側の回数 × 内側の回数 で考えられます。

for文をネストすると何が起こるか

for文をネストすると、処理の流れは次のようになります。

順番動き
1外側のループが1回目を始める
2内側のループが最初から最後まで動く
3外側のループが2回目に進む
4内側のループがまた最初から最後まで動く
5外側のループが終わるまで同じ流れを続ける

ここでポイントになるのは、内側のループは外側の1回ごとに最初からやり直すということです。

外側が1回目なら、内側は1から最後まで動きます。
外側が2回目に進むと、内側はまた1から始まります。
外側が3回目に進んでも、内側はまた1から始まります。

鬼滅の刃風にたとえると、外側のループが「第1訓練場、第2訓練場、第3訓練場……」と進みます。
そして、それぞれの訓練場に入るたびに、内側のループが「第1の型、第2の型、第3の型……」をすべて確認します。

図:外側の1回ごとに内側が全部動く

↓クリックすると拡大表示されます。

この図が示していること

この図では、外側のループ row が1回進むたびに、内側のループ col が1から3まで動くことを示しています。

row が 1 のとき、col は 1、2、3 と進みます。
row が 2 になると、col はまた 1、2、3 と進みます。
同じ流れが row = 4 まで続きます。

外側が4回、内側が3回なので、全体では 4 × 3 = 12回 の処理になります。

ここから分かることは、ネストしたfor文では、外側と内側の回数を掛け算で考えると全体の処理回数を把握しやすいということです。

for文のネストを確認する

まずは、for文の中にfor文を書く基本的な例を見ていきます。

ファイル名:Sample7.java

class Sample7
{
    public static void main(String[] args)
    {
        for(int row = 1; row <= 4; row++){
            for(int col = 1; col <= 3; col++){
                System.out.println("第" + row + "訓練場、" + col + "番目の型を確認します。");
            }
        }
    }
}

実行結果

第1訓練場、1番目の型を確認します。
第1訓練場、2番目の型を確認します。
第1訓練場、3番目の型を確認します。
第2訓練場、1番目の型を確認します。
第2訓練場、2番目の型を確認します。
第2訓練場、3番目の型を確認します。
第3訓練場、1番目の型を確認します。
第3訓練場、2番目の型を確認します。
第3訓練場、3番目の型を確認します。
第4訓練場、1番目の型を確認します。
第4訓練場、2番目の型を確認します。
第4訓練場、3番目の型を確認します。

このプログラムでは、外側のfor文が row を 1 から 4 まで変化させています。

for(int row = 1; row <= 4; row++)

内側のfor文は、col を 1 から 3 まで変化させています。

for(int col = 1; col <= 3; col++)

つまり、row が1つ進むたびに、col が 1、2、3 とすべて動きます。

Sample7.javaの動き

Sample7.java の動きを表で整理すると、次のようになります。

外側 row内側 col の動き
11 → 2 → 3
21 → 2 → 3
31 → 2 → 3
41 → 2 → 3

row が 1 のとき、col は 1、2、3 と進みます。
そのあと row が 2 になります。
すると、col はまた 1、2、3 と進みます。

この流れが row が 4 になるまで続きます。

rowcol表示される内容の考え方
11第1訓練場、1番目の型
12第1訓練場、2番目の型
13第1訓練場、3番目の型
21第2訓練場、1番目の型
22第2訓練場、2番目の型
23第2訓練場、3番目の型

このように、外側の row が行のような大きなまとまりを担当し、内側の col がその中の細かい位置を担当しています。

全体では何回処理されるのか

ネストしたfor文では、実行回数を掛け算で考えると分かりやすいです。

Sample7.java では、外側のループは4回動きます。
内側のループは、外側1回ごとに3回動きます。

そのため、全体では次の回数になります。

4 × 3 = 12回
外側の回数内側の回数合計
4回3回12回

多重ループでは、この合計回数を意識することがとても大切です。

処理が思ったより多く実行されることもあるため、外側と内側がそれぞれ何回動くのかを確認すると安心です。

鬼滅の刃風にたとえると、4つの訓練場それぞれで3つの型を確認するので、全部で12回の型確認になります。

外側と内側の役割を意識しよう

ネストしたfor文を読むときは、どちらが外側で、どちらが内側なのかを意識することが大切です。

Sample7.java では、次のように役割を分けています。

変数役割
row外側のループを担当する
col内側のループを担当する

row は、訓練場の番号を表しています。
col は、その訓練場の中で確認する型の番号を表しています。

このように、変数名に意味を持たせると、ネストしたfor文が読みやすくなります。

よく i や j を使う書き方もあります。
ただ、学習の初期段階では、row や col のように役割が分かる名前を使うと理解しやすいです。

変数名読みやすさ
i、j短く書けるが、役割が見えにくいことがある
row、col行と列の役割が分かりやすい
outer、inner外側と内側の関係が分かりやすい

鬼滅の刃風にたとえると、row は訓練場の場所、col はその場所で確認する型の順番です。
場所と型を別々に管理することで、処理の流れが整理しやすくなります。

for文のネストは表や座標の処理に強い

for文のネストは、行と列のような2つの軸を扱う場面でとても便利です。

Sample7.java の動きは、表のマスを順番に見ていくような処理だと考えられます。

row \ col123
1(1,1)(1,2)(1,3)
2(2,1)(2,2)(2,3)
3(3,1)(3,2)(3,3)
4(4,1)(4,2)(4,3)

この表では、row が縦方向、col が横方向を表しています。

for文のネストを使えば、左上から順番にマスを確認するような処理が書けます。

使い道ネストの考え方
表のマスを処理する外側が行、内側が列
座標を確認する外側が縦、内側が横
模様を出力する外側が行、内側が文字
組み合わせを調べる外側と内側で2つの値を組み合わせる

Javaの学習が進むと、配列や表形式のデータを扱う場面でも、この考え方が役立ちます。

if文と組み合わせると表現の幅が広がる

ネストできるのは、for文どうしだけではありません。

for文の中にif文を入れると、繰り返しながら条件に応じて処理を変えられます。

たとえば、次のようなことができます。

組み合わせできること
for文 + if文条件に合うときだけ表示を変える
ネストしたfor文 + if文表や模様の中で条件に応じた表示をする
for文 + boolean変数状態を切り替えながら処理する

これにより、ただ同じ処理を繰り返すだけでなく、規則的な模様や条件つきの出力も作れるようになります。

鬼滅の刃風にたとえると、訓練場を順番に回りながら、条件に応じて「丸印の型」と「四角印の型」を切り替えて刻むようなものです。

多重ループとif文を組み合わせる

次に、ネストしたfor文とif文を組み合わせて、記号を交互に表示するプログラムを見ていきます。

ファイル名:Sample8.java

class Sample8
{
    public static void main(String[] args)
    {
        boolean circle = true;  // 最初は○から表示する

        for(int row = 0; row < 4; row++){
            for(int col = 0; col < 6; col++){
                if(circle == true){
                    System.out.print("○");
                    circle = false;
                }
                else{
                    System.out.print("■");
                    circle = true;
                }
            }
            System.out.print("\n");
        }
    }
}

実行結果

○■○■○■
○■○■○■
○■○■○■
○■○■○■

このプログラムでは、外側のfor文で行を4回くり返しています。

for(int row = 0; row < 4; row++)

内側のfor文では、1行あたり6文字を表示しています。

for(int col = 0; col < 6; col++)

つまり、4行 × 6文字 の模様を表示しています。

Sample8.javaのしくみ

Sample8.java では、boolean型の変数 circle を使って、次に表示する記号を管理しています。

boolean circle = true;

boolean型には、true と false の2つの値だけを入れられます。

意味
true
false

このプログラムでは、circle が true なら ○ を表示します。
circle が false なら ■ を表示します。

条件表示する文字その後の値
circle が truefalse にする
circle が falsetrue にする

このように、表示するたびに circle の値を切り替えています。

if(circle == true){
    System.out.print("○");
    circle = false;
}
else{
    System.out.print("■");
    circle = true;
}

circle が true のときは、○ を表示したあと false にします。
次の処理では circle が false なので、■ を表示して true に戻します。

この切り替えによって、○と■が交互に表示されます。

鬼滅の刃風にたとえると、circle は「次に刻む印を決める札」です。
true なら丸の印、false なら四角の印を刻みます。
1つ刻むたびに札を裏返すため、○と■が交互に並びます。

改行の意味にも注目しよう

Sample8.java では、内側のループが終わるたびに改行しています。

System.out.print("\n");

System.out.print は、表示したあと自動では改行しません。
そのため、内側のループの中では ○ や ■ が横に並びます。

1行分の6文字を表示し終えたあと、外側のループの中で \n を表示して改行しています。

場所役割
内側のfor文1行分の記号を横に表示する
System.out.print("\n")1行が終わったら改行する
外側のfor文行を4回くり返す

もし改行がなければ、すべての記号が横一列に表示されます。

○■○■○■○■○■○■○■○■○■○■○■

改行があることで、4行の模様として見やすく表示されます。

Sample8.javaの表示を表で見る

Sample8.java の表示結果を、表のように見ると次のようになります。

表示結果
1行目○■○■○■
2行目○■○■○■
3行目○■○■○■
4行目○■○■○■

外側のループは、行を作っています。
内側のループは、1行の中の6文字を作っています。

ループ役割
外側のfor文4行を作る
内側のfor文1行あたり6文字を作る
if文○と■を切り替える
boolean変数次に表示する記号を管理する
改行次の行へ移る

このように、ネストしたfor文にif文を組み合わせると、単純な繰り返しよりも表現の幅が広がります。

図:多重ループとif文で模様を作る

↓クリックすると拡大表示されます。

この図が示していること

この図では、Sample8.java の多重ループとif文の役割を示しています。

外側のfor文 row は、4行分の繰り返しを担当します。
内側のfor文 col は、1行の中に6文字を表示する役割です。
if文は、circle の値によって ○ と ■ を切り替えます。

内側のループが終わったところで \n によって改行するため、次の行へ移れます。

ここから分かることは、多重ループでは外側と内側の役割を分け、さらにif文を組み合わせることで、規則的な模様や表形式の出力が作れるということです。

多重ループでできること

for文のネストを使うと、いろいろな表現ができるようになります。

できること
表形式の処理行と列を順番に処理する
規則的な模様の表示○と■、*と- を並べる
組み合わせの列挙2つの値の全組み合わせを出す
条件つきの繰り返しif文と組み合わせて表示を変える
座標の確認縦横の位置を順番に処理する

多重ループは、少し複雑な処理を書くための大切な技術です。

特に、2次元の表やマス目を扱うときには、外側を行、内側を列と考えると整理しやすくなります。

鬼滅の刃風にたとえると、多重ループは「戦場のマス目を順番に確認していく巡回」です。
外側で行を進み、内側でその行の列を確認します。
そこにif文を加えると、条件に応じて印を変えることもできます。

for文のネストでよくある混乱

ネストしたfor文では、最初のうちは「どの変数がどこで動いているのか」が分からなくなることがあります。

そんなときは、次の点を確認すると整理しやすくなります。

見るポイント確認する内容
外側の変数大きな繰り返しを何回するか
内側の変数外側1回の中で何回動くか
ブロックの範囲どこまでが内側のループか
合計回数外側 × 内側 で求められるか
表示の改行どこで次の行へ移るか

特に、中かっこの位置を見失うと混乱しやすいです。

for(int row = 0; row < 4; row++){
    for(int col = 0; col < 6; col++){
        処理;
    }
    改行;
}

この形では、内側のfor文が終わったあとに改行しています。
つまり、1行分の処理が終わったら次の行へ進むという流れです。

場所意味
内側のfor文の中1文字ずつ表示する
内側のfor文の外、外側のfor文の中1行が終わった後の処理
外側のfor文の外すべての行が終わった後の処理

インデントをきれいにそろえると、どこまでが内側の処理なのかが見やすくなります。

for文のネストを読むときのコツ

for文のネストを読むときは、いきなり全体を理解しようとせず、次の順番で見ると分かりやすいです。

順番見ること
1外側のfor文が何回動くか
2内側のfor文が何回動くか
3内側で何をしているか
4内側が終わったあと何をしているか
5全体で何回処理されるか

Sample7.java なら、外側は4回、内側は3回です。
そのため、表示は合計12回です。

Sample8.java なら、外側は4回、内側は6回です。
そのため、記号は合計24個表示されます。

プログラム外側内側合計
Sample7.java4回3回12回
Sample8.java4回6回24回

このように、まず回数を整理すると、多重ループの動きがかなり見えやすくなります。

for文のネストを学ぶ意味

for文のネストは、単にループを2つ重ねるだけの書き方ではありません。

縦と横を組み合わせた処理、規則的なパターンの出力、条件つきの反復、座標や表の処理など、プログラムの表現力を広げるための大切な考え方です。

学べること内容
多重の繰り返し繰り返しの中でさらに繰り返す
外側と内側の役割分担大きな流れと細かい処理を分ける
表形式の処理行と列を扱える
条件との組み合わせif文で表示や処理を切り替えられる
実行回数の見積もり外側 × 内側 で考えられる

最初は少し難しく感じるかもしれません。
でも、基本はとてもシンプルです。

外側のループが1回進む。
そのたびに、内側のループが全部動く。
これを外側のループが終わるまで続ける。

この流れをつかめば、多重ループはかなり理解しやすくなります。

鬼滅の刃風にたとえると、for文のネストは「広い戦場を行ごとに進みながら、各行の中の印を1つずつ確認する巡回の型」です。
外側が大きな移動を担当し、内側が細かい確認を担当します。

この考え方を身につけると、表、模様、配列、座標、組み合わせなど、より実践的なJavaプログラムにもつなげやすくなります。