配列
この章では、同じ型のデータをまとめて管理する 配列 について学ぶ。 配列を使うことで、大量のデータを効率的に扱えるようになる。
この章で得られるスキル:
- ✅ 大量のデータを効率的に管理できる
- ✅ 成績一覧や在庫リストなど実用的なプログラムが作れる
- ✅ ループと組み合わせて一括処理ができる
- ✅ 表形式のデータを扱える
Step 0: 配列がないとどうなる?
問題:クラスの成績を管理したい
30人のクラスで、全員のテストの点数を管理するプログラムを書きたい。
配列がない場合
public class ScoreManagement {
public static void main(String[] args) {
// 30人分の変数が必要...
int score1 = 85;
int score2 = 90;
int score3 = 78;
int score4 = 92;
// ... あと26個の変数
// 平均を計算するには?
int sum = score1 + score2 + score3 + score4; // + ... あと26個
double average = sum / 30.0;
// 最高点を探すには?
int max = score1;
if (score2 > max) max = score2;
if (score3 > max) max = score3;
// ... あと27回の比較
}
}
問題点:
- 30個の変数を書くのが大変
- 変数名を考えるのが大変(score1, score2, ...)
- ループで処理できない(同じ処理を30回書く必要がある)
- 生徒数が増えたら、すべてのコードを書き直す必要がある
配列がある場合
public class ScoreManagement {
public static void main(String[] args) {
// 30人分の点数を1つの配列で管理
int[] scores = {85, 90, 78, 92, /* ... */};
// 平均を計算(ループで簡単)
int sum = 0;
for (int score : scores) {
sum += score;
}
double average = sum / scores.length;
// 最高点を探す(ループで簡単)
int max = scores[0];
for (int score : scores) {
if (score > max) {
max = score;
}
}
}
}
配列を使うメリット:
- 1つの変数で大量のデータを管理できる
- ループで効率的に処理できる
- データ数が変わってもコードを変える必要がない
では、配列の使い方を詳しく学んでいこう。
Step 1: 配列の基本
配列とは
配列(Array) は、 同じ型のデータを順番に並べて管理する仕組み である。
複数のデータを1つの変数名でまとめて扱える。
インデックス(添字)
配列の各要素には、 インデックス(添字) という番号が付けられている。
重要:インデックスは0から始まる(最初の要素がインデックス0)
| インデックス: | 0 | 1 | 2 | 3 | 4 |
| 値: | 85 | 90 | 78 | 92 | 88 |
↑ | ↑ |
なぜ0から始まるのか?
プログラミングの世界では、メモリのアドレス計算の効率化のため、インデックスを0から始める慣習がある。 「0番目、1番目、2番目...」と数える。
最初は違和感があるかもしれないが、すぐに慣れる。
実行してみよう:
やってみよう:
scores[2](3人目)の点数を表示してみようscores[10]にアクセスしてエラーを確認してみよう(範囲外エラーが発生する)
Step 2: 配列の宣言と初期化
配列の宣言
配列を使うには、まず 宣言 する。
型[] 配列名;
例:
int[] scores; // int型の配列
String[] names; // String型の配列
double[] prices; // double型の配列
配列には、基本データ型(int, double, boolean)やクラス型(String, 自作クラス)など、どんな型でも使える。
配列の初期化
配列を使う前に、 初期化(メモリの確保)が必要である。
方法1:サイズを指定して初期化
int[] scores = new int[5]; // 5個の要素を持つ配列
この場合、すべての要素は 初期値 で初期化される:
- int, double →
0または0.0 - boolean →
false - String, クラス型 →
null
方法2:値を指定して初期化
int[] scores = {85, 90, 78, 92, 88};
この場合、配列のサイズは自動的に決まる(この例では5)。
方法3:宣言と初期化を分ける
int[] scores;
scores = new int[]{85, 90, 78, 92, 88};
配列の長さ
配列の長さ(要素数)は、 配列名.length で取得できる。
int[] scores = {85, 90, 78, 92, 88};
System.out.println(scores.length); // 5
Javaの配列は、一度作成すると 長さを変更できない。
後からサイズを変えたい場合は、ArrayListなどのコレクションを使う必要がある。
ArrayListについては、第15章「コレクション」で学ぶ。
実行してみよう:
やってみよう:
new int[5]をnew int[10]に変えて、サイズを変更してみようscores配列に別の値を追加してみよう
Step 3: 配列の要素へのアクセス
要素の読み取り
配列の要素を読み取るには、 インデックス を指定する。
配列名[インデックス]
例:
int[] scores = {85, 90, 78, 92, 88};
int firstScore = scores[0]; // 85(最初の要素)
int secondScore = scores[1]; // 90(2番目の要素)
int lastScore = scores[4]; // 88(最後の要素)
要素の書き換え
配列の要素を書き換えるには、インデックスを指定して代入する。
int[] scores = {85, 90, 78, 92, 88};
scores[0] = 100; // 最初の要素を100に変更
scores[2] = 95; // 3番目の要素を95に変更
インデックスの範囲
インデックスは0から始まり、配列の長さ - 1まで
長さ5の配列なら、有効なインデックスは0, 1, 2, 3, 4
存在しないインデックスにアクセスすると、 ArrayIndexOutOfBoundsException(配列の範囲外エラー)が発生する。
int[] scores = {85, 90, 78};
int value = scores[5]; // エラー!(インデックス5は存在しない)
プログラムが強制終了するので、注意が必要である。
実行してみよう:
やってみよう:
scores[2]を別の値に変更してみようscores.length - 1を使って、最後の要素を安全にアクセスしてみよう
Step 4: 配列とfor文
配列とfor文を組み合わせると、すべての要素を効率的に処理できる。
基本パターン
for (int i = 0; i < 配列名.length; i++) {
// 配列名[i]で各要素にアクセス
}
例:すべての要素を表示
int[] scores = {85, 90, 78, 92, 88};
for (int i = 0; i < scores.length; i++) {
System.out.println(scores[i]);
}
インデックスが必要な処理
インデックスを使うと、要素の位置情報も活用できる。
例:何番目かを表示
for (int i = 0; i < scores.length; i++) {
System.out.println((i + 1) + "人目: " + scores[i] + "点");
}
例:要素の書き換え(全員に10点加算)
for (int i = 0; i < scores.length; i++) {
scores[i] += 10;
}
実行してみよう:
やってみよう:
- 80点以上の人数をカウントしてみよう
- 全員から5点減点するプログラムを書いてみよう
Step 5: 拡張for文(for-each)
拡張for文とは
拡張for文(for-each文)は、配列のすべての要素を順番に処理するための簡潔な構文である。
for (型 変数名 : 配列) {
// 変数に要素が順番に代入される
}
例:
int[] scores = {85, 90, 78, 92, 88};
for (int score : scores) {
System.out.println(score);
}
通常のfor文と拡張for文の比較
通常のfor文:
for (int i = 0; i < scores.length; i++) {
System.out.println(scores[i]);
}
拡張for文:
for (int score : scores) {
System.out.println(score);
}
拡張for文の方が、シンプルで読みやすい。
使い分け
| 通常のfor文 | 拡張for文(for-each) |
|---|---|
| インデックスが必要な場合 | 要素だけが必要な場合 |
| 要素を書き換える場合 | 要素を読み取るだけの場合 |
| 特定の範囲を処理する場合 | すべての要素を処理する場合 |
拡張for文では、インデックスが取得できない。 また、要素の書き換えができない(読み取り専用)。 これらが必要な場合は、通常のfor文を使う。
実行してみよう:
やってみよう:
- 拡張for文を使って、平均点を計算してみよう
fruits配列に別の果物を追加してみよう
Step 6: 配列の実用例
配列を使った実用的な処理パターンを学ぼう。
パターン1:合計と平均
int[] scores = {85, 90, 78, 92, 88};
int sum = 0;
for (int score : scores) {
sum += score;
}
double average = (double) sum / scores.length;
パターン2:最大値・最小値
int[] scores = {85, 90, 78, 92, 88};
int max = scores[0]; // 最初の要素で初期化
for (int score : scores) {
if (score > max) {
max = score;
}
}
int min = scores[0];
for (int score : scores) {
if (score < min) {
min = score;
}
}
パターン3:検索(特定の値を探す)
int[] scores = {85, 90, 78, 92, 88};
int target = 90;
int index = -1; // 見つからなかった場合は-1
for (int i = 0; i < scores.length; i++) {
if (scores[i] == target) {
index = i;
break;
}
}
if (index != -1) {
System.out.println(target + "点は" + (index + 1) + "人目");
} else {
System.out.println(target + "点の人はいません");
}
パターン4:条件に合う要素の数をカウント
int[] scores = {85, 90, 78, 92, 88};
int count = 0;
for (int score : scores) {
if (score >= 80) {
count++;
}
}
System.out.println("80点以上の人数: " + count + "人");
実行してみよう:
やってみよう:
- 70点未満の人数をカウントしてみよう
- 平均点以上の人数をカウントしてみよう
Step 7: 2次元配列
2次元配列とは
2次元配列 は、 配列の配列 である。
表形式のデータ(例:成績表、座席表、ゲームマップ)を扱うときに使う。
行(row)
列(column)
0 1 2
┌────┬────┬────┐
0 │ 85 │ 90 │ 78 │ ← 1人目の成績(国語、数学、英語)
├────┼────┼────┤
1 │ 92 │ 88 │ 95 │ ← 2人目の成績
├────┼────┼────┤
2 │ 76 │ 82 │ 89 │ ← 3人目の成績
└────┴────┴────┘
2次元配列の宣言と初期化
型[][] 配列名 = {
{要素, 要素, 要素},
{要素, 要素, 要素},
{要素, 要素, 要素}
};
例:
int[][] scores = {
{85, 90, 78}, // 1人目の成績
{92, 88, 95}, // 2人目の成績
{76, 82, 89} // 3人目の成績
};
2次元配列の要素へのアクセス
配列名[行][列]
例:
int value = scores[0][0]; // 85(1人目の国語)
int value2 = scores[1][2]; // 95(2人目の英語)
2次元配列とループ
2次元配列を処理するには、 ネストしたループ を使う。
for (int i = 0; i < scores.length; i++) { // 行(生徒)
for (int j = 0; j < scores[i].length; j++) { // 列(科目)
System.out.print(scores[i][j] + " ");
}
System.out.println();
}
実用例:成績表
String[] students = {"太郎", "花子", "次郎"};
String[] subjects = {"国語", "数学", "英語"};
int[][] scores = {
{85, 90, 78}, // 太郎の成績
{92, 88, 95}, // 花子の成績
{76, 82, 89} // 次郎の成績
};
// 各生徒の平均点を計算
for (int i = 0; i < students.length; i++) {
int sum = 0;
for (int j = 0; j < scores[i].length; j++) {
sum += scores[i][j];
}
double average = (double) sum / scores[i].length;
System.out.println(students[i] + "の平均: " + average + "点");
}
実行してみよう:
やってみよう:
- 新しい生徒を追加してみよう
- 新しい科目(例:理科)を追加してみよう
Step 8: 実践課題
課題1:週間売上管理システム
ある店舗の1週間(月〜日)の売上データを配列で管理し、以下の情報を表示するプログラムを作成せよ。
要件:
- 7日間の売上を配列に格納
- 合計売上を計算
- 平均売上を計算
- 最高売上の日と金額を表示
- 最低売上の日と金額を表示
サンプルデータ:
int[] sales = {45000, 52000, 48000, 61000, 58000, 72000, 68000};
String[] days = {"月", "火", "水", "木", "金", "土", "日"};
実行例:
週間売上レポート
合計売上: 404000円
平均売上: 57714円
最高売上: 土曜日 72000円
最低売上: 月曜日 45000円
課題2:座席予約システム
映画館の座席予約システムを作成せよ。座席を2次元配列で管理し、予約・キャンセルができるようにする。
要件:
- 5行6列の座席表を作成(0: 空席、1: 予約済み)
- 座席表を表示(◯: 空席、✕: 予約済み)
- 特定の座席を予約する
- 特定の座席をキャンセルする
- 空席数を表示
サンプルコード:
やってみよう:
- キャンセル機能を追加してみよう
- 予約率(予約済み / 全座席数 × 100)を計算してみよう
- 特定の行の空席数を表示してみよう
課題3:成績分析システム
3人の生徒の3科目(国語、数学、英語)の成績を管理し、以下の情報を表示するプログラムを作成せよ。
要件:
- 2次元配列で成績を管理
- 各生徒の合計点と平均点を表示
- 各科目の平均点を表示
- 全体の最高点と最低点を表示
サンプルデータ:
String[] students = {"太郎", "花子", "次郎"};
String[] subjects = {"国語", "数学", "英語"};
int[][] scores = {
{85, 90, 78}, // 太郎の成績
{92, 88, 95}, // 花子の成績
{76, 82, 89} // 次郎の成績
};
実行例:
=== 各生徒の成績 ===
太郎: 合計 253点、平均 84.3点
花子: 合計 275点、平均 91.7点
次郎: 合計 247点、平均 82.3点
=== 各科目の平均点 ===
国語: 84.3点
数学: 86.7点
英語: 87.3点
=== 全体統計 ===
最高点: 95点
最低点: 76点
まとめ
この章では、Javaの 配列 について学んだ。
学んだ内容
- 配列 は同じ型のデータをまとめて管理する仕組みである
- インデックスは0から始まる(最初の要素は
配列名[0]) - 配列の宣言と初期化の方法
new int[5](サイズ指定){1, 2, 3}(値指定)
配列名.lengthで配列の長さを取得できる- 配列の要素へのアクセス(読み取り、書き換え)
- 範囲外アクセスで ArrayIndexOutOfBoundsException が発生する
- 通常のfor文 と 拡張for文 で配列を処理できる
- 通常のfor文:インデックスが必要、要素を書き換える
- 拡張for文:要素を読み取るだけ、シンプル
- 配列の実用例(合計、平均、最大値、最小値、検索、カウント)
- 2次元配列 で表形式のデータを扱える
次のステップ
次の章では、 メソッド について学ぶ。 メソッドと配列を組み合わせることで、複雑なデータ処理を整理して書けるようになる。
FAQ
Q1: なぜインデックスは0から始まるのか?
A: プログラミングの世界では、メモリのアドレス計算の効率化のため、インデックスを0から始める慣習がある。
配列の先頭アドレスに「0個分移動」=最初の要素、「1個分移動」=2番目の要素、という計算になる。
最初は違和感があるかもしれないが、多くのプログラミング言語で採用されている標準的な方式である。
Q2: 配列とArrayListの違いは?
A: 主な違いは以下の通り:
| 配列 | ArrayList |
|---|---|
| サイズが固定 | サイズが可変 |
int[] scores | ArrayList<Integer> scores |
| プリミティブ型OK | クラス型のみ |
| 高速 | やや遅い |
配列: サイズが決まっている場合に使う ArrayList: 後からデータを追加・削除する場合に使う
ArrayListについては、第15章「コレクション」で詳しく学ぶ。
Q3: 配列のサイズは後から変更できないの?
A: Javaの配列は、一度作成すると サイズを変更できない。
サイズを変更したい場合は、以下の方法がある:
-
新しい配列を作って、要素をコピーする
int[] oldArray = {1, 2, 3};
int[] newArray = new int[5]; // 新しいサイズ
for (int i = 0; i < oldArray.length; i++) {
newArray[i] = oldArray[i];
} -
ArrayListを使う(推奨)
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
// いつでも追加・削除できる
データ数が変わる可能性がある場合は、最初からArrayListを使う方が良い。
Q4: 配列を引数として渡すとどうなる?
A: 配列を引数として渡すと、 参照が渡される(参照渡し)。
つまり、メソッド内で配列の要素を変更すると、 呼び出し元の配列も変更される。
public class ArrayReference {
public static void main(String[] args) {
int[] numbers = {1, 2, 3};
System.out.println("変更前: " + numbers[0]); // 1
changeArray(numbers);
System.out.println("変更後: " + numbers[0]); // 100(変更されている!)
}
public static void changeArray(int[] arr) {
arr[0] = 100; // 呼び出し元の配列が変更される
}
}
これは、配列が 参照型 であるためである。
プリミティブ型(int, doubleなど)は値渡しだが、配列やクラスは参照渡しになる。
Q5: 多次元配列はいつ使うの?
A: 2次元配列は、 表形式のデータ を扱うときに使う。
よくある使用例:
-
成績表(生徒 × 科目)
int[][] scores = {
{85, 90, 78}, // 太郎の成績
{92, 88, 95} // 花子の成績
}; -
座席表(行 × 列)
int[][] seats = {
{0, 1, 0}, // 1行目(0: 空席、1: 予約済み)
{1, 1, 0} // 2行目
}; -
ゲームマップ(縦 × 横)
int[][] map = {
{0, 0, 1}, // 0: 通路、1: 壁
{0, 1, 0}
}; -
画像データ(縦 × 横のピクセル)
「行と列」の概念がある場合は、2次元配列が適している。
3次元配列以上も作れるが、実務ではあまり使わない。