Java
2021.12.10
Javaのfor文を使ったループ処理 | 拡張for文の使い方や注意点【初心者向け】
2023.11.15


1.Javaのfor文とは?

for文は、初期化式、条件式、変化式から構成される繰り返し処理です。

for(初期化式; 条件式; 変化式){
    // 繰り返し処理
}

基本の形はこのようになります。

式を書き換えることで、「○○回繰り返す」という単純な処理以外にも様々な条件での繰り返し処理を記述できます。

2.for文の基本的な書き方


条件式の役割について詳しく見ていきましょう。

①初期化式

初期化式はfor文が実行される際、最初に1回のみ実行される式です。

通常、ループ回数を表すカウンターなど「ループによって変化する変数」を宣言、または初期化します。

②条件式

条件式は、for文内の繰り返し処理を実行する「前」に評価されます。評価結果がtrueなら処理が実行され、falseなら処理は実行されずにfor文が終了します。

③変化式

変化式は、for文内の処理が最後まで行われた後に実行される文です。ここで実行された結果を受け、再び条件式の評価が行われます。



3.for文の基本的なルール


for文の基本的なルールについてサンプルコードを交えて解説します。

①初期化した変数のスコープ

変数には「スコープ」と呼ばれる「変数が利用できる範囲」があります。スコープの外側では変数を使えません。そのため、for文内の初期化式で宣言した変数はそのブロックの中でしか参照できないのです。


下の例では、for文内で変数iを宣言しているため、スコープはfor文の中までです。

for (int i = 0; i < 5; i++) {
    // 繰り返し処理
}

System.out.printIn(i); // エラー発生

for文の外で変数iを使いたい場合は、下の例のようにfor文を記述する前に宣言しておく必要があります。

int i; // 外側で宣言
for (i = 0; i < 5; i++) {
    // 繰り返し処理
}

System.out.println(i);

出力:

5

for文を抜けたときのiの値は、最後に変化式でi++をし条件式のi<5が不成立になった値なので、5になっています。

②条件式は必ずboolean型を返す 

Javaのfor文では、条件式の返す値はboolean型である必要があります。for文が同じ形をしているC言語、JavaScriptではboolean型以外も使用可能です。


下の例のように、条件式を整数の5にすると、int型をboolean型に変換できないためエラーが発生します。

for (int i = 0; 5; i++) { // エラー発生
    // 繰り返し処理
}



4.for文の応用的な書き方


for文を効率よく活用するための、応用的な記述方法について解説します。

①ブロックを省略する

for文の繰り返し処理を囲む波括弧{}をなくすことで、ブロックを省略できます。ブロックを省略すると、for文の中では最初の1行のみが実行されます。


下の例を実行するとどうなるでしょうか。ブロックを省略し、処理文を2行記述しました。

for (int i = 0; i < 5; i++)
    System.out.println("1行目");
    System.out.println("2行目");

/* この記述と同じ意味
for (int i = 0; i < 5; i++){
    System.out.println("1行目");
}
System.out.println("2行目");
*/

出力:

1行目
1行目
1行目
1行目
1行目
2行目

”1行目”が5回出力された後、”2行目”が1回だけ出力されています。つまり、for文の中で繰り返し処理が行われたのは1行目だけで、2行目はfor文の外側にある文として実行されたということです。


このように波括弧{}を省略することは可能ですが、実際に開発をする際にはプログラミングのミスを防止するため、ブロックを省略することは推奨されていません。

②for文の初期化式・条件式・変化式を省略する

初期化式、条件式、変化式も省略可能です。

・初期化式

for文の外で宣言を行うことで、初期化式を省略できます。ただし、セミコロン(;)が必要なことに注意しましょう。

int i = 0;  // 外側で宣言
for (; i < 5; i++) { // ; は残して初期化式を省略
    // 繰り返し処理
}

・条件式

条件式も同じように省略できます。条件式をブロックの中で別に定義する場合などに省略されます。

for (int i = 0;; i++) { // ; は残して条件式を省略
    if (i >= 5) { // 条件式を定義
        break;
    }
    // 繰り返し処理
}

ブロックの中で条件式を定義せず省略した場合、条件式は常にtrueとして扱われ、無限ループになってしまうので気をつけてください。

・変化式

変化式も省略できます。

for (int i = 0; i < 5;) { // 変化式を省略
    // 繰り返し処理
    i++; // 変化式を定義
}

条件式と同じように、ブロックの中で変化式を定義しない場合、カウンターの値が変わらずループが終わらなくなってしまうので注意しましょう。

③複数の初期化式・変化式を使用する

初期化式、変化式は複数使用することもできます。

int i, j; // 外側で宣言
for (i = 0, j = 5; i < 5; i++, j--) { // 初期化式、変化式を複数使用
    // 繰り返し処理
}
System.out.println(i);
System.out.println(j);

出力:

5
0

上の例では変数iは0から1ずつ増え、変数jは5から1ずつ減ります。iが5以上になれば繰り返しが終了するので、終了時にはi=5、j=0となります。


ただし、初期化式を複数使用する場合には注意が必要です。


例えば以下のように、初期化式を宣言するとエラーが発生してしまいます。

for (int i = 0, int j = 5; i < 5; i++, j--) { // エラー発生
    // 繰り返し処理
}

もし初期化式の中で同じデータ型を複数宣言したい場合は、それぞれにデータ型をつけるのではなく、「int i=0, j=5」のように最初に共通のデータ型を書きましょう。


また、違うデータ型を複数宣言することはできません。

for (int i = 0, double j = 5.0; i < 5; i++, j--) { // エラー発生
    // 繰り返し処理
}

違うデータ型を複数宣言する際は、for文の外側で2つのデータ型を別々に宣言する必要があります。

int i;  // 外側でiを宣言
double j;  // 外側でjを宣言
for (i = 0, j = 5.0; i < 5; i++, j--) { 
    // 繰り返し処理
}

④入れ子のfor文の書き方

for文の中にさらにfor文が記載されるような多重構造を、「入れ子」といいます。for文を入れ子にして使うことで、より複雑なループ処理が可能になるのです。

for (int i = 0; i < 3; i++) {  // iのループ
    for (int j = 0; j < 3; j++) {  // jのループ
        System.out.println(i + "-" + j);
    }
}

出力:

0-0
0-1
0-2
1-0
1-1
1-2
2-0
2-1
2-2

出力では、ループごとに変数iとjの値を表示しています。iの1回のループ内でjが3回ループ処理を行っているのがわかりますね。


このように、入れ子にすることによりfor文で表現できる幅は広がりますが、多重ループが多すぎるとプログラムの可読性といった面で問題が発生します。入れ子を多用しすぎないよう注意してください。



5.for文の処理を途中で抜けるには


for文の処理を途中で終わらせるにはどうすれば良いのでしょうか? 2つの方法を紹介します。

①break文で処理を終了する

break文は、for文などのループ処理を中断し終了させるための文です。if文などで条件を提示した中で使われます。

for (int i = 0; i < 5; i++) {
    if (i == 3) { // i=3のときループから抜けて終了
        break;
    }
    System.out.println(i);
}

出力:

0
1
2

if文でi=3のときにbreak文が実行されるようにしました。この文が入ったことにより、i=3になった時点でループが中断され終了します。出力文がbreak文よりもあとに記述されているので、3は出力されません。


for文が入れ子になっている場合、break文を囲んだ最も内側のループのみ終了します。外側のループからも抜けるためには、ラベル付きbreak文を使いましょう。


まずはラベル付きではないbreak文で二重ループのfor文を抜けた例を見てみます。

for (int i = 0; i < 3; i++) { // iのループ
    for (int j = 0; j < 3; j++) { // jのループ
        if (j == 1) { // j=1のときループから抜けて終了
            break;
        }
        System.out.println(i + "-" + j);
    }
}

出力:

0-0
1-0
2-0

j=1のとき内側のループは中断し終了する、という処理を外側のループで3回行っています。出力結果を見ると、内側のループだけ終了していることがわかります。


次に、ラベル付きbreak文で抜けた例を見てみましょう。

exLabel: for (int i = 0; i < 3; i++) { // iのループ
    for (int j = 0; j < 3; j++) { // jのループ
        if (j == 1) { // j=1のときループから抜けて終了
            break exLabel;
        }
        System.out.println(i + "-" + j);
    }
}

出力:

0-0

外側のループの前に「exLabel:」、breakの後に「exLabel」が追加されていますね。この二か所に同じ名前のラベルをつけることによって、j=1になったとき外側のループからも同時に抜けられます。


出力を見てみると、i=0, j=0のループ以降は出力がありません。j=1のときにiのループもjのループも終了したことがわかります。

②continue文で処理をスキップする

continue文を使うとその回の処理を中断し、スキップして次の周回へと進みます。

for (int i = 0; i < 5; i++) {
    if (i == 3) { // i=3のときループ内で後続処理をスキップ
        continue;
    }
    System.out.println(i);
}

出力:

0
1
2
4

i=3のときに処理をスキップしますが、ループ自体は終了せずループの先頭から次の処理を行うため、それ以降の出力が行われます。出力を見ると3以外は出力されており、i=3の時にのみ処理がスキップされたことがわかるでしょう。


break文と同じく、continue文を囲んだ最も内側のループのみ終了するため、外側までスキップするにはラベル付きcontinue文を使います。


まずはラベル付きではないcontinue文で二重ループのfor文を抜けた例を見てみましょう。

for (int i = 0; i < 3; i++) { // iのループ
    for (int j = 0; j < 3; j++) { // jのループ
        if (j == 1) { // j=1のときループから抜けてスキップ
            continue;
        }
        System.out.println(i + "-" + j);
    }
}

出力:

0-0
0-2
1-0
1-2
2-0
2-2

j=1でjのループから抜け、次の処理にスキップしています。iのループはスキップされず、そのまま行われていることが確認できました。


次にこのfor文からラベル付きcontinue文で抜けてみます。

exLabel: for (int i = 0; i < 3; i++) { // iのループ
    for (int j = 0; j < 3; j++) { // jのループ
        if (j == 1) { // j=1のときループから抜けてスキップ
            continue exLabel;
        }
        System.out.println(i + "-" + j);
    }
}

出力:

0-0
1-0
2-0

ラベルを付けたことによって、j=1のときにjのループだけでなくiのループも次の周回にスキップしていることがわかります。


最初のうちは、どのfor文を抜けたのか出力しながら確かめていくと理解がしやすくなります。

6.for文を使うと便利なシーン

for文はどのようなシーンでよく使われるのしょうか? 実際にプログラミング開発で使われる場面について解説します。

①配列へのアクセス

for文がよく使われる場面として、配列へのアクセスがあります。for文を使うことによって順番に配列の要素を表示できます。

String[] exArray = { "a", "b", "c", "d" }; // 配列を宣言、作成
for (int i = 0; i < exArray.length; i++) {
    System.out.println("exArray[" + i + "] = " + exArray[i]);
}

出力:

exArray[0] = a
exArray[1] = b
exArray[2] = c
exArray[3] = d

条件式に使われているexArray.lengthは、「配列.length」で配列の長さを取得しています。


多次元配列にも同じようにアクセスできます。

String[][] exArray = { { "a", "b", "c", "d" }, { "A", "B", "C", "D" } };// 配列を宣言、作成
for (int i = 0; i < exArray.length; i++) {
    for (int j = 0; j < exArray[i].length; j++) {
        System.out.println("exArray[" + i + "][" + j + "] = " + exArray[i][j]);
    }
}

出力:

exArray[0][0] = a
exArray[0][1] = b
exArray[0][2] = c
exArray[0][3] = d
exArray[1][0] = A
exArray[1][1] = B
exArray[1][2] = C
exArray[1][3] = D

for文を入れ子にすることで、多次元配列にアクセスできました。外側、内側両方のループの条件式で配列のlengthを参照しています。

②Listへのアクセス

Listへのアクセスもfor文で簡単に行えます。


まずは、Iteratorでアクセスする方法を見てみましょう。

import java.util.Arrays;    // 必要なインポート
import java.util.Iterator;
import java.util.List;

public class Java_for {
    public static void main(String[] args) {
        List<String> exList = Arrays.asList("a", "b", "c", "d"); // リストを宣言、作成
        for (Iterator<String> itr = exList.iterator(); itr.hasNext();) {
            System.out.println(itr.next());
        }
    }
}

出力:

a
b
c
d

初期化式でiteratorを取得し、itrに格納しています。hasNext()は次の要素が存在すればtrueを返し、next()では次の要素を返します。iteratorを使うとListのサイズなどを気にせずアクセスできるので、エラーなどが起こりにくくなるのが利点です。


次に、インデックスを使ってListにアクセスしてみましょう。

// インポートなどは省略
List<String> exList = Arrays.asList("a", "b", "c", "d"); // リストを宣言、作成
for (int i = 0; i < exList.size(); i++) {   
    System.out.println(exList.get(i));
}

出力:

a
b
c
d

条件式のsize()はListの要素数を返します。出力の際のget()でListの要素を取り出しています。基本のfor文とあまり変わらないので、わかりやすいのではないでしょうか。



7.拡張for文

①拡張for文とは

拡張for文は、配列、コレクションなど要素に1つずつアクセスするようなループをコンパクトに書くためのfor文です。

②for文との違いは?

拡張for文は、通常のfor文と違いカウンターや要素数を書く必要がなく、より簡単に記述できるのが特徴です。ただし、配列やコレクションに順番にアクセスする場合しか使えません。


一部の要素にアクセスしたり、アクセスする順番を変えたりする場合には通常のfor文を使いましょう。

③拡張for文の書き方

拡張for文は以下のように記述できます。

for(要素の型 任意の変数名 : 配列・コレクション名){
    // 繰り返す処理
}

アクセスする要素の型、変数名と配列名、コレクション名を書くだけです。


試しにコレクションの一つであるListにアクセスしてみます。

List<String> exList = Arrays.asList("a", "b", "c", "d");
for (String s : exList) {
    System.out.println(s);
}

出力:

a
b
c
d




8.for文を使う際の注意点

①無限ループに気をつける

for文は繰り返しを行う文なので、記述した式によっては無限ループになってしまうことがあります。

for (int i = 0;; i++) { // 条件式を省略
    // 繰り返し処理
}

例えばこのように条件式を省略した場合、ループが終わらず処理をずっと繰り返すことになります。

for (int i = 0; i < 5; i--) { 
// 繰り返し処理
}

条件式が書いてあっても、上のように条件式が必ずtrueになってしまうような場合にも無限ループが発生してしまいます。変化式に対して条件式が正しいか、確認してみるといいかもしれません。


処理が重くなった、パソコンが熱くなったと感じる場合、気付かず無限ループが発生していることもあります。CPUの使用率などを確認してみましょう。



この記事をシェア