Javaの制御構造(繰り返し)
2025-08-01はじめに
制御構文を理解することは、Javaプログラミングにおいて非常に重要です。制御構造を使いこなすことで、プログラムに判断能力を持たせることができ、条件によって処理を分岐させることが可能になります。
また、繰り返し処理を効率的に記述できるため、同じ処理を何度も書く必要がなくなり、無駄のないコードになります。さらに、条件分岐やループ構造を適切に使うことで、コードの可読性と保守性が向上し、他の人にも理解しやすいプログラムを書くことができます。
これらの知識を身につけることで、より複雑で高度なアルゴリズムの実装も可能になり、実践的なプログラミングスキルの向上につながります。繰り返し処理(for/while)について、基礎から応用まで詳細に解説します。
ループ構造:for文
基本的なfor文
for文は、指定した回数だけ処理を繰り返す場合に使用します。あらかじめ回数が決まっている繰り返しに適しており、配列や数値のカウント処理などでよく使われます。
for (初期化式; 条件式; 更新式) {
// 繰り返し実行する処理
}
具体例として1から10まで表示するプログラムを作成します。
for (int i = 1; i <= 10; i++) {
System.out.println(i);
}
このコードは、Javaの基本的なfor文を使った繰り返し処理の例です。
変数iを1から10まで1ずつ増やしながら、System.out.println(i);でその値を順に出力します。
処理の流れは次の通りです。
- 初期化:
int i = 1;が最初に1回だけ実行されます。 - 条件判定:
i <= 10がtrueの間、ループが続きます。 - 処理実行:
System.out.println(i);が実行されます。 - 更新処理:
i++によりiの値が1増えます。 - 条件が
falseになる(iが11になる)とループ終了。
その結果、コンソールには次のように1〜10の数字が1行ずつ出力されます。
さまざまなfor文の使用例
逆順のループ:次のコードは、Javaのfor文を使って10から1までの数を逆順に出力する例です。
for (int i = 10; i >= 1; i--) {
System.out.println(i);
}
for文の構成要素は次の通りです。
- 初期化:
int i = 10;により、ループ変数iを10で初期化します。 - 条件式:
i >= 1がtrueの間、ループが続きます。 - 更新処理:
i--により、ループのたびにiが1ずつ減ります。
処理の流れは以下のようになります。
iが10でスタート。条件i >= 1は真なので出力。iが9, 8, … と1まで減少しながら順に出力。iが0になると条件がfalseとなりループ終了。
ステップを2ずつ増加:次のコードは更新処理で毎回2ずつ増加させてます。
for (int i = 0; i <= 10; i += 2) {
System.out.println(i); // 0, 2, 4, 6, 8, 10
}
for文の3つの要素の動きは次の通りです。
- 初期化:
int i = 0;により、カウンタ変数iを0で初期化します。 - 条件式:
i <= 10の間、ループが続きます。 - 更新処理:
i += 2により、iの値が毎回2ずつ増加します。
この結果、iの値は 0 → 2 → 4 → 6 → 8 → 10 と変化し、それぞれがSystem.out.println(i);で出力されます。
複数の変数を管理:次のコードは、for文の初期化部と更新部に複数の変数を指定する例です。
for (int i = 0, j = 10; i < j; i++, j--) {
System.out.println("i: " + i + ", j: " + j);
}
変数iは0から1ずつ増加し、jは10から1ずつ減少します。i < jの間だけループが続きます。処理の流れを簡単に追うと次のようになります。
| ループ回数 | iの値 | jの値 | 出力内容 |
|---|---|---|---|
| 1回目 | 0 | 10 | i: 0, j: 10 |
| 2回目 | 1 | 9 | i: 1, j: 9 |
| 3回目 | 2 | 8 | i: 2, j: 8 |
| 4回目 | 3 | 7 | i: 3, j: 7 |
| 5回目 | 4 | 6 | i: 4, j: 6 |
5回目の後にiが5、jが5となり、条件i < jがfalseになるためループ終了します。
このように、for文では複数の変数を同時に制御しながらループ処理を行うことができ、たとえば両端から中央に向かって処理するようなアルゴリズム(ソートや文字列反転など)にも応用できます。
拡張for文(for-each文)
配列やコレクションの要素を順番に処理する簡潔な構文です。拡張for文は、配列やコレクションの全要素を順番に処理したいときに使われる簡潔な書き方です。
for (要素の型 変数名 : 配列またはコレクション) {
// 各要素に対する処理
}
- 要素の型:配列やリストの中のデータ型(例:
int、Stringなど) - 変数名:各ループで現在の要素が代入される変数
- 配列またはコレクション:繰り返し処理したい対象
拡張for文は、配列やリストの要素を順番に処理する際に便利な構文です。インデックス指定(numbers[i])を使わずに各要素を扱えるため、コードを短く書けて読みやすくなります。また、要素の読み取り専用処理に向いており、安全にデータを扱える点も利点です。ただし、拡張for文では配列やリストの要素を直接変更することはできません。要素の値を更新したい場合は、通常のfor文を使ってインデックス経由でアクセスする必要があります。
int[] numbers = {1, 2, 3, 4, 5};
for (int num : numbers) {
System.out.println(num);
}
配列numbersには {1, 2, 3, 4, 5} が格納されており、for (int num : numbers) の部分で、各ループごとに配列の要素が左側の変数numに代入されます。ループの中では System.out.println(num); によって、その値が1つずつ出力されます。
次のコードは、Javaの拡張for文(for-each文)を使って文字列の配列を順に処理する例です。
String[] fruits = {"Apple", "Banana", "Orange"};
for (String fruit : fruits) {
System.out.println(fruit);
}
for (String fruit : fruits) の部分では、配列fruitsの各要素が1つずつ変数fruitに代入され、ループのたびに System.out.println(fruit); によって出力されます。
このように拡張for文を使うと、インデックス指定(fruits[i])を使わずに配列の全要素を簡潔に処理でき、コードが短く読みやすくなります。
ループ構造:while文
while文の基本構文
while文は、条件がtrueである限り処理を繰り返します。繰り返す回数があらかじめ決まっていない場合や、条件に応じて動的に処理を続けたい場合に使われます。
while (条件式) {
// 繰り返し実行する処理
}
- 条件式が
trueの間、ブロック内の処理が繰り返し実行されます。 - 条件が
falseになるとループを抜け、次の処理へ進みます。
次のコードは、Javaのwhile文を使って1から10までの数を順に出力する基本的な例です。
int i = 1;
while (i <= 10) {
System.out.println(i);
i++;
}
変数iを1で初期化し、while (i <= 10) の条件がtrueの間、ループ内の処理を繰り返します。
ループの中では、まずSystem.out.println(i);で現在のiの値を表示し、その後にi++でiを1ずつ増やします。
処理の流れは以下のようになります。
iが1のとき → 出力してiが2に増加iが2〜10の間 → 同様に出力を繰り返すiが11になると条件i <= 10がfalseとなり、ループ終了
do-while文
do-while文は、最低1回は処理を実行し、その後条件をチェックします。
do {
// 繰り返し実行する処理
} while (条件式);
doブロック内の処理を最初に1回必ず実行します。- その後で
whileの条件式を評価し、trueなら再び処理を繰り返します。 falseになるとループを終了します。
次のコードは、do-while文を使ってユーザーに1〜10の範囲内の数値を入力させるプログラムです。Scannerクラスでキーボード入力を受け取り、条件を満たすまで繰り返します。
import java.util.Scanner;
Scanner scanner = new Scanner(System.in);
int input;
do {
System.out.print("1から10の間の数を入力してください: ");
input = scanner.nextInt();
} while (input < 1 || input > 10);
System.out.println("正しい入力: " + input);
do-while文の特徴である「必ず1回は処理を実行する」性質が活かされています。最初の入力が不正でも、再度入力を求めることができるため、ユーザー入力の検証(バリデーション)に最適なパターンです。
■ 処理の流れ
Scanner scanner = new Scanner(System.in);
→ ユーザー入力を受け取る準備をします。do { ... } while (条件);
→ 少なくとも1回は入力を促し、入力が条件を満たさない限り繰り返します。System.out.print("1から10の間の数を入力してください: ");
→ ユーザーに入力を求めます。input = scanner.nextInt();
→ 入力された数値を変数inputに代入します。while (input < 1 || input > 10);
→ 入力値が1未満または10より大きい場合、再び入力を求めます。- 条件を満たすとループを抜け、
System.out.println("正しい入力: " + input);が実行されます。
while文 vs for文
while文とfor文はいずれも**繰り返し処理(ループ)**を行うための構文ですが、目的や使う場面が異なります。どちらを選ぶかは、「繰り返しの条件が明確かどうか」によって判断するのが基本です。
| 特徴 | while文 | for文 |
|---|---|---|
| 適した場面 | 繰り返し回数が不明な場合 | 繰り返し回数が明確な場合 |
| 初期化 | ループ外で行う | 初期化式内で行える |
| 更新処理 | ループ内で行う | 更新式で行える |
| 可読性 | 条件のみに集中 | 初期化・条件・更新が一箇所 |
■ 使い分けの目安
- 繰り返し回数が決まっている → for文
例:「10回繰り返す」「配列の要素数だけ処理する」など。 - 繰り返し条件が状況によって変わる → while文
例:「入力値が正しいまで」「データが残っている間」など。
ループ制御文
**ループ制御文(loop control statement)**とは、Javaの繰り返し構文(for文、while文、do-while文)などで、ループの流れを途中で制御するための文のことです。通常、ループは条件がfalseになるまで繰り返しますが、ループ制御文を使うことで、途中でスキップしたり、強制的に抜けたりできます。
break文
breakは、現在のループ処理を強制的に終了させます。条件に関係なく、即座にループの外へ抜けることができます。
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break; // iが5になるとループを抜ける
}
System.out.println(i);
}
// 出力: 1 2 3 4
continue文
continueは、現在の繰り返しをスキップして次のループに進むための文です。ループ全体は終了せず、条件判定に戻ります。
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) {
continue; // 偶数の場合はスキップ
}
System.out.println(i);
}
// 出力: 1 3 5 7 9
return文
returnは、ループだけでなくメソッド自体の処理を終了させます。
※クラス・メソッドについては別記事で詳しく書いてます。
for (int i = 1; i <= 5; i++) {
if (i == 3) {
return; // メソッド全体を終了
}
System.out.println(i);
}
// 出力: 1 2
ラベル付きbreak/continue
ネストしたループで外側のループを制御する場合に使用します。次のコードは、ラベル付きのbreak文を使って「外側のループ全体」を抜ける例です。
outerLoop: // ラベル
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
if (i * j > 4) {
break outerLoop; // 外側のループを抜ける
}
System.out.println(i + " * " + j + " = " + (i * j));
}
}
通常、break文は現在のループ(内側)だけを終了しますが、ラベル(ここでは outerLoop:)を付けることで、指定した外側のループまで一気に抜けることができます。
実践的な使用例
素数判定プログラム
次のコードは、変数numberに代入された整数が素数かどうかを判定するプログラムです。まず、1以下の数は素数ではないためisPrimeをfalseにします。それ以外の数については、2からその平方根までの整数で割り切れるかを調べ、割り切れた場合は素数ではないと判断しループを終了します。最終的に、三項演算子を使って結果を出力しています。
int number = 29;
boolean isPrime = true;
if (number <= 1) {
isPrime = false;
} else {
for (int i = 2; i <= Math.sqrt(number); i++) {
if (number % i == 0) {
isPrime = false;
break;
}
}
}
System.out.println(number + (isPrime ? " は素数です" : " は素数ではありません"));
フィボナッチ数列の生成
次のコードは、指定した回数分のフィボナッチ数列を出力するプログラムです。最初にaとbを0と1で初期化し、ループのたびにaを出力します。その後、aとbの和をsumに代入し、次の項を計算するためにaにbを、bにsumを代入して更新します。これを繰り返すことで、0から始まるフィボナッチ数列の最初の10項が順に表示されます。
int n = 10; // 生成する項の数
int a = 0, b = 1;
System.out.println("フィボナッチ数列:");
for (int i = 1; i <= n; i++) {
System.out.print(a + " ");
int sum = a + b;
a = b;
b = sum;
}
九九表の表示
このコードは、二重のfor文を使って九九の表を出力するプログラムです。外側のループで掛けられる数iを1から9まで繰り返し、内側のループで掛ける数jを1から9まで繰り返します。各組み合わせでi * jの結果を計算し、System.out.printf("%2d ", i * j);によって桁を揃えて表示します。内側のループが1〜9まで完了するたびに改行を入れることで、1の段から9の段まで整った掛け算表が出力されます。
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= 9; j++) {
System.out.printf("%2d ", i * j);
}
System.out.println();
}
よくある間違いとベストプラクティス
無限ループ
while (true)によってループが常に実行され、System.out.println("無限ループ");が何度も出力され続けます。終了条件がないため、プログラムは自動的に止まりません。実行を終了するには、強制的に停止させる必要があります(例:コンソールでCtrl + C)。条件が常にtrueであるため、永久に繰り返し続ける無限ループの例です。
while (true) { // 条件が常にtrue
System.out.println("無限ループ");
// 終了条件がない
}
無限ループは、サーバーの監視やゲームのメインループなどで意図的に使われることもありますが、終了条件を設けないとプログラムが停止しなくなるため、使用には注意が必要です。
浮動小数点数の比較
for文でdouble型の変数dを使って0.1ずつ加算していく例ですが、浮動小数点の誤差問題により正しく終了しない可能性があります。double型は2進数で小数を表現するため、0.1のような値を正確に保持できません。その結果、dが理論上は1.0になるはずでも、実際には0.999999999のような値になり、条件式d != 1.0が永遠にtrueのままになることがあります。このような場合は、整数を使って管理する方法が安全です。たとえばfor (int i = 1; i <= 10; i++) { double d = i * 0.1; ... }のように書くことで、誤差の影響を回避できます。
for (double d = 0.1; d != 1.0; d += 0.1) { // 誤差が発生する可能性
System.out.println(d);
}
ループ処理を書く際のベストプラクティスとして、まずループ条件はできるだけシンプルにし、複雑な条件判定が必要な場合はループ内でif文を使うようにします。また、無限ループを防ぐために必ず終了条件を確認し、処理が終わる見通しを明確にしておくことが大切です。
繰り返し回数が決まっている場合はfor文を、条件によって継続を判断する場合はwhile文を使うなど、目的に応じて適切な構文を選びましょう。さらに、不要な処理を避けるためには条件が満たされた時点で早めにbreak文でループを抜けるのが効果的です。最後に、ループのネスト(入れ子)は浅く保つことで、コードの可読性と保守性を高めることができます。
まとめ
Javaにおけるループ構文にはそれぞれ適した使い方があります。for文は、繰り返しの回数があらかじめ決まっている場合に適しており、カウンタ変数を使って指定回数だけ処理を繰り返す際に便利です。一方、while文は条件に基づいて繰り返す構文で、繰り返しの回数が決まっていないときや、特定の条件を満たすまで処理を続けたい場合に使われます。また、ループの途中で処理を制御するための文として、breakやcontinueがあります。breakはループ自体を強制的に終了させ、continueはその回の処理をスキップして次のループへ進みます。これらを使い分けることで、効率的で意図の明確な繰り返し処理を記述することができます。
演習問題
初級レベル(3問)
問題1:基本的なfor文
// for文を使用して、1から10までの数字を表示するプログラムを作成してください
public class Main {
public static void main(String[] args) {
// ここにfor文を記述
}
}
問題2:while文の基本
// while文を使用して、5から1までの数字をカウントダウン表示するプログラムを作成してください
public class Main {
public static void main(String[] args) {
// ここにwhile文を記述
}
}
問題3:配列とfor文の組み合わせ
// for文を使用して、配列numbersのすべての要素を表示するプログラムを作成してください
public class Main {
public static void main(String[] args) {
int[] numbers = {10, 20, 30, 40, 50};
// ここにfor文を記述
}
}
中級レベル(6問)
問題4:合計値の計算
// for文を使用して、1から100までの整数の合計値を計算し表示するプログラムを作成してください
public class Main {
public static void main(String[] args) {
int sum = 0;
// ここにfor文を記述
System.out.println("1から100までの合計: " + sum);
}
}
問題5:条件付きループ(while)
// while文を使用して、乱数(1〜10)を生成し、5が出るまで繰り返すプログラムを作成してください
// 各回の乱数値も表示すること
public class Main {
public static void main(String[] args) {
// ヒント: Math.random()を使用(0.0以上1.0未満の乱数)
// ここにwhile文を記述
}
}
問題6:break文の使用
// for文とbreak文を使用して、1から20までの数字を表示するが、
// 13が出た時点でループを終了するプログラムを作成してください
public class Main {
public static void main(String[] args) {
// ここにfor文とbreakを記述
}
}
問題7:continue文の使用
// for文とcontinue文を使用して、1から10までの数字のうち、
// 奇数のみを表示するプログラムを作成してください
public class Main {
public static void main(String[] args) {
// ここにfor文とcontinueを記述
}
}
問題8:二重ループ
// 二重for文を使用して、以下のような九九表の一部(1の段から3の段まで)を表示するプログラムを作成してください
// 1 × 1 = 1
// 1 × 2 = 2
// ...
// 3 × 9 = 27
public class Main {
public static void main(String[] args) {
// ここに二重for文を記述
}
}
問題9:do-while文の使用
// do-while文を使用して、ユーザーに入力を求め、
// "exit"と入力されるまで繰り返すプログラムを作成してください
// (Scannerを使用せず、固定値でシミュレーションしてください)
public class Main {
public static void main(String[] args) {
String input = "start";
int count = 0;
// ここにdo-while文を記述
// 3回目で"exit"になるようにする
}
}
上級レベル(3問)
問題10:配列の検索
// for文を使用して、配列の中から特定の値(target)が最初に見つかる位置(インデックス)を検索するプログラムを作成してください
// 見つかった場合はそのインデックスを、見つからない場合は-1を表示すること
public class Main {
public static void main(String[] args) {
int[] numbers = {45, 23, 67, 89, 12, 34};
int target = 67;
int foundIndex = -1;
// ここにfor文を記述
System.out.println("見つかった位置: " + foundIndex);
}
}
問題11:ループ制御の組み合わせ
// 1から50までの数字について、以下の条件を満たすプログラムを作成してください
// - 3の倍数の場合は"Fizz"と表示
// - 5の倍数の場合は"Buzz"と表示
// - 3と5の倍数の場合は"FizzBuzz"と表示
// - それ以外は数字を表示
// continue文を効果的に使用すること
public class Main {
public static void main(String[] args) {
// ここにfor文とcontinueを記述
}
}
問題12:文字列処理とループ
// for文を使用して、文字列を逆順に表示するプログラムを作成してください
// 例: "Hello" → "olleH"
public class Main {
public static void main(String[] args) {
String text = "Programming";
String reversed = "";
// ここにfor文を記述
System.out.println("元の文字列: " + text);
System.out.println("逆順: " + reversed);
}
}
初級レベル(3問)解答例
問題1 解答例
// for文を使用して、1から10までの数字を表示するプログラムを作成してください
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
System.out.println(i);
}
}
}
問題2 解答例
// while文を使用して、5から1までの数字をカウントダウン表示するプログラムを作成してください
public class Main {
public static void main(String[] args) {
int count = 5;
while (count >= 1) {
System.out.println(count);
count--;
}
}
}
問題3 解答例
// for文を使用して、配列numbersのすべての要素を表示するプログラムを作成してください
public class Main {
public static void main(String[] args) {
int[] numbers = {10, 20, 30, 40, 50};
for (int i = 0; i < numbers.length; i++) {
System.out.println("numbers[" + i + "] = " + numbers[i]);
}
}
}
中級レベル(6問)解答例
問題4 解答例
// for文を使用して、1から100までの整数の合計値を計算し表示するプログラムを作成してください
public class Main {
public static void main(String[] args) {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
System.out.println("1から100までの合計: " + sum);
}
}
問題5 解答例
// while文を使用して、乱数(1〜10)を生成し、5が出るまで繰り返すプログラムを作成してください
public class Main {
public static void main(String[] args) {
int randomNum;
do {
randomNum = (int)(Math.random() * 10) + 1;
System.out.println("生成された数: " + randomNum);
} while (randomNum != 5);
System.out.println("5が出ました!ループ終了");
}
}
問題6 解答例
// for文とbreak文を使用して、1から20までの数字を表示するが、
// 13が出た時点でループを終了するプログラムを作成してください
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 20; i++) {
if (i == 13) {
System.out.println("13が見つかったためループを終了します");
break;
}
System.out.println(i);
}
}
}
問題7 解答例
// for文とcontinue文を使用して、1から10までの数字のうち、
// 奇数のみを表示するプログラムを作成してください
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) {
continue; // 偶数の場合はスキップ
}
System.out.println(i);
}
}
}
問題8 解答例
// 二重for文を使用して、以下のような九九表の一部(1の段から3の段まで)を表示するプログラムを作成してください
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 9; j++) {
System.out.println(i + " × " + j + " = " + (i * j));
}
System.out.println(); // 段の間に空行を挿入
}
}
}
問題9 解答例
// do-while文を使用して、ユーザーに入力を求め、
// "exit"と入力されるまで繰り返すプログラムを作成してください
public class Main {
public static void main(String[] args) {
String input = "start";
int count = 0;
do {
count++;
System.out.println("ループ回数: " + count);
// 3回目で"exit"になるようにシミュレーション
if (count == 3) {
input = "exit";
System.out.println("exitが入力されました");
} else {
input = "continue";
System.out.println("入力: " + input);
}
} while (!input.equals("exit"));
System.out.println("プログラム終了");
}
}
上級レベル(3問)解答例
問題10 解答例
// for文を使用して、配列の中から特定の値(target)が最初に見つかる位置(インデックス)を検索するプログラムを作成してください
public class Main {
public static void main(String[] args) {
int[] numbers = {45, 23, 67, 89, 12, 34};
int target = 67;
int foundIndex = -1;
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] == target) {
foundIndex = i;
break; // 最初に見つかった時点でループを抜ける
}
}
System.out.println("見つかった位置: " + foundIndex);
}
}
問題11 解答例
// 1から50までの数字について、FizzBuzzプログラムを作成してください
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 50; i++) {
// 3と5の倍数の場合
if (i % 3 == 0 && i % 5 == 0) {
System.out.println("FizzBuzz");
continue;
}
// 3の倍数の場合
if (i % 3 == 0) {
System.out.println("Fizz");
continue;
}
// 5の倍数の場合
if (i % 5 == 0) {
System.out.println("Buzz");
continue;
}
// それ以外
System.out.println(i);
}
}
}
// 別解:文字列結合を使用した方法
/*
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 50; i++) {
String output = "";
if (i % 3 == 0) output += "Fizz";
if (i % 5 == 0) output += "Buzz";
if (output.equals("")) {
output = String.valueOf(i);
}
System.out.println(output);
}
}
}
*/
問題12 解答例
// for文を使用して、文字列を逆順に表示するプログラムを作成してください
public class Main {
public static void main(String[] args) {
String text = "Programming";
String reversed = "";
// 文字列の末尾から先頭に向かってループ
for (int i = text.length() - 1; i >= 0; i--) {
reversed += text.charAt(i);
}
System.out.println("元の文字列: " + text);
System.out.println("逆順: " + reversed);
}
}
// 別解:StringBuilderを使用した方法(より効率的)
/*
public class Main {
public static void main(String[] args) {
String text = "Programming";
StringBuilder reversed = new StringBuilder();
for (int i = text.length() - 1; i >= 0; i--) {
reversed.append(text.charAt(i));
}
System.out.println("元の文字列: " + text);
System.out.println("逆順: " + reversed.toString());
}
}
*/