Javaプログラミング入門

10. 配列

最終更新:

javatutorial

- view
管理者のみ編集可

配列とは

配列とは、同じ種類のデータをまとめて扱うことができる仕組みです。

想像してみてください。
あなたはボールを16個持っています。
それぞれのボールに数字を割り当てたいとしましょう。
でも現在の知識では、このように書くしかありません。
  1. int ball1 = 0;
  2. int ball2 = 1;
  3. int ball3 = 2;
  4. int ball4 = 3; // ...ずっと続く
まだ、ビリヤードのようにボールが16個ならどうにか頑張れそうな気もします。
しかし、ビンゴの玉になると75個に増えますし、この数が100個、1000個と増えると
変数を定義するだけでも大変になってしまいます。
また、変数の管理も大変で、名前の付け間違いや、数の数え間違いが起こるリスクも高まります。

このような問題を解決してくれるのが配列になります。

配列のイメージ

イメージしやすい例として「くつ箱」や「ロッカー」を考えてみましょう。
くつ箱には同じサイズのスペースが並んでいて、それぞれに番号が振られています。
番号を使えば、どの場所に何があるか簡単に把握できます。

こちらが配列のイメージになります。

たとえば「番号2のロッカーに入っている値は?」と聞かれたら、すぐに「75」と答えられます。
Javaでは、このようにして番号を使って値を知ることができます。
そして、この番号の事を、添え字(Index, インデックス)と呼びます。
また、一つのロッカーに入っている値の事を要素(Element, エレメント)と呼びます。

配列の使い方

Javaにおいて、変数も配列も使い方の基本は「宣言 → 代入 → 参照」です。
つまり、配列は変数の応用形であり、基本の考え方は変わりません。
この時点では、まだ中身はありません。

配列の宣言


配列の宣言記載方法は
[] 配列名; 
になります。
型にはデータ型を指定し、配列名には、変数名と同じく配列の名前を指定します。

サンプル:ArraySample.java
  1. public class ArraySample {
  2. public static void main(String[] args) {
  3. int[] balls;
  4. }
  5. }

配列の生成

通常の変数では、宣言をしたらそのまま代入することができました。
int num; // 宣言
num = 10; // 代入 
しかし、配列はそのままでは値を代入することができません。
配列は、同じ種類のデータをいくつもまとめてしまえる箱のセットのようなものです。
でも、使う前に「いくつ箱が必要なのか」を先に決めなければなりません。

配列の生成する際の記載方法は
配列名 = new[要素数]; 
になります。
配列名には、変数名と同じく配列の名前を指定します。
代入演算子を記載した後に「new」というキーワードを記載する必要があります。
その次に、型にはデータ型を指定し、要素数にはいくつ箱を用意する必要があるのかという数値を指定します。

サンプル:ArraySample.java
  1. public class ArraySample {
  2. public static void main(String[] args) {
  3. int[] balls;
  4. balls = new int[5];
  5. }
  6. }
これは、「5個分のボールを入れるための箱(balls)を準備してください」という意味です。
このいくつ箱を用意する必要があるのかを指定する要素数にはint型の整数値を入れるという決まりがあります。
[5] は、5個の箱が必要という指定になります。

配列へ代入

先ほどの配列のイメージを見てみましょう。

前にお話ししたように、配列は「くつ箱」や「ロッカー」のように、同じ大きさの箱がズラッと並んでいるイメージです。
それぞれの箱には「添え字(Index, インデックス)」がついていて、その番号を使って中身を操作します。
たとえば、「番号2のロッカーに3を入れる」としたら、Javaでは次のように書きます。
配列の宣言記載方法は
配列名[2] =; 
になります。

しかし、ここで気をつけたいポイントがあります。
たとえば scores[2] = 75; と書いた場合、これは「2番目のロッカーに入れる」という意味ではありません。
実はこのとき、3番目のロッカーに値を入れていることになります。
なぜなら、Javaではロッカーの番号(添え字)が0から始まるというルールがあるからです。

つまり
添え字0 → 1番目のロッカー
添え字1 → 2番目のロッカー
添え字2 → 3番目のロッカー
このように、「添え字の数字 + 1」が、実際のロッカーの順番と一致します。
サンプル:ArraySample.java
  1. public class ArraySample {
  2. public static void main(String[] args) {
  3. int[] balls;
  4. balls = new int[5];
  5. balls[0] = 9;
  6. balls[1] = 12;
  7. balls[2] = 8;
  8. balls[3] = 3;
  9. balls[4] = 5;
  10. }
  11. }

配列の参照

では、代入した値を参照して、画面にしてみましょう。
参照する際は代入と同じように、
配列名[添え字] 
と記載することで参照することが可能になります。
今回は、System.out.println()で値を画面に出力してみます。
サンプル:ArraySample.java
  1. public class ArraySample {
  2. public static void main(String[] args) {
  3. int[] balls;
  4. balls = new int[5];
  5. balls[0] = 9;
  6. balls[1] = 12;
  7. balls[2] = 8;
  8. balls[3] = 3;
  9. balls[4] = 5;
  10. System.out.println(balls[0]);
  11. System.out.println(balls[1]);
  12. System.out.println(balls[2]);
  13. System.out.println(balls[3]);
  14. System.out.println(balls[4]);
  15. }
  16. }
実行結果
9
12
8
3
5
各配列に代入された要素の値が正しく出力されています。

配列の注意点

1.添字は int型 である

配列の添字に使えるのは、int型またはbyte型、short型です。
long型やfloat型などのデータ型は使用できません。

2.添字には変数・定数・式も使える

添字には、数値のほかに変数や計算式も使用可能です。
サンプル:ArrayCareful.java
  1. public class ArrayCareful {
  2. public static void main(String[] args) {
  3. int i = 1;
  4. int[] scores = new int[5];
  5. scores[i] = 95; // scores[1] に代入
  6. scores[i + 1] = 100; // scores[2] に代入
  7. System.out.println(scores[i + 1]);
  8. }
  9. }
実行結果
100 

3.配列の生成について

Javaでは、配列を生成(new)したとき、各要素は自動的に初期値が設定されます。
つまり、配列の要素を明示的に初期化しなくても、中身には値が入っています
配列の型 初期値
整数型(int[]) 0
小数型(double[]) 0.0
真偽値型(boolean[]) false
文字列型(String[]) null
その他参照型 null
サンプル:ArrayInit.java
  1. public class ArrayInit {
  2. public static void main(String[] args) {
  3. int[] numbers;
  4. numbers = new int[3];
  5. System.out.println(numbers[0]);
  6. System.out.println(numbers[1]);
  7. System.out.println(numbers[2]);
  8. }
  9. }
実行結果
0
0
0 

配列の初期化

配列も変数同様に初期化をすることができます。
初期化の方法は3種類あります。

① 要素数だけ指定して初期化

int[] numbers = new int[5]; 
例:初期化のイメージ

このコードは、int型の配列の箱を5個分確保するという意味です。
ただし、中身(要素)には値を入れていません。
このように初期化した配列には、先程の説明同様、自動的に初期値が入ります

② 値を指定して初期化

int[] scores = {80, 90, 100, 40, 55}; 
例:初期化のイメージ

この書き方は、配列を作成すると同時に、値も設定して初期化します。
このとき、配列の要素数は指定不要で、中括弧 {} にある要素の数が自動で決まります。
int[] scores = new int[] {80, 90, 100, 40, 55}; 
例:初期化のイメージ

こちらの書き方も、上と全く同じ配列を生成します。
違いとしては
上の書き方は、変数の宣言と同時に初期化する場合のみ使えます。
int[] scores = {80, 90, 100, 40, 55}; // これはOK
int[] scores2;
scores2 = {80, 90, 100, 40, 55}; // これはNG 
下の書き方は、どこでも使える初期化構文になります。
int[] scores = new int[] {80, 90, 100, 40, 55}; // これもOK
int[] scores2;
scores2 = new int[] {80, 90, 100, 40, 55};  // これもOK 

配列の.lengthとfor文の組み合わせ

Javaの配列には、自分の配列の大きさ(要素の数)を教えてくれる方法があります。
それが.lengthです。
サンプル:ArrayLength.java
  1. public class ArrayLength {
  2. public static void main(String[] args) {
  3. int[] numbers = new int[5];
  4. System.out.println(numbers.length);
  5. }
  6. }
実行結果
5 
このように.lengthは「この配列には何個の箱があるか?」を教えてくれます。

先程、配列はロッカーが横に並んでいるようなイメージとして例えました。
それぞれのロッカーには番号(添字)がついていて
サンプル:ArrayLength.java
  1. public class ArrayLength {
  2. public static void main(String[] args) {
  3. int[] numbers = new int[5];
  4. System.out.println(numbers.length);
  5. }
  6. }
サンプルだとnumbers[0] から numbers[4] まで、合計5個のロッカーがあります。
このロッカーの「」を教えてくれるのが .length です。
つまり、ロッカーが何個あるかを調べたいときは、.lengthを使えばいいのです。

for文と.lengthの組み合わせ

ロッカーを先頭から1つずつ順番に開けて、全体をチェックしたいときは
for文と.lengthを組み合わせて、こんなふうに書くことができます。
サンプル:ArrayLength.java
  1. public class ArrayLengthAndFor {
  2. public static void main(String[] args) {
  3. int[] numbers = new int[5];
  4. for (int i = 0; i < numbers.length; i++) {
  5. System.out.println(i + "番目のロッカー: " + numbers[i]);
  6. }
  7. }
  8. }
実行結果
0番目のロッカー: 0
1番目のロッカー: 0
2番目のロッカー: 0
3番目のロッカー: 0
4番目のロッカー: 0 

なぜ.lengthを使うのか?

まず、.lengthとは配列が持つ特別な情報で、「自分がいくつの要素を持っているか」を教えてくれる仕組みです。
例えば、int[] numbers = new int[5];
という配列があれば、numbers.lengthは「5」という値を返します。
これは、配列自身が自分の大きさを正確に知っていて、それを私たちに教えてくれる「魔法の道具」のようなものです。

なぜ数字を直接書かずに.lengthを使うのか

.lengthを使用する理由は、主に以下の4つの重要なメリットがあります。

1つめは、変更に強く、修正が楽になります。(保守性・柔軟性)
最初は5個の配列で作ったプログラムも、後から10個に変更する必要が生じることがよくあります。
もしfor (int i = 0; i < 5; i++)のように「5」を直接書いていた場合
配列の宣言部分を「new int[10]」に変更しても、for文の「5」を「10」に直し忘れる事故が起きる可能性があります。

.lengthを使えば、配列のサイズ宣言を変更するだけで、for文は自動的に新しいサイズに対応します。
これにより、修正漏れによるバグを完全に防ぐことができます。

2つめは、安全にエラーを防ぐことができます。(安全性)
配列の有効な添え字(インデックス)は0からlength-1までです。
この範囲を超えてアクセスしようとすると
ArrayIndexOutOfBoundsExceptionという深刻なエラーが発生し、プログラムが停止してしまいます。

i < numbers.length」という条件式を使うことで
ループ変数iが必ず配列の有効な範囲内に収まることが機械的に保証されます。
人間の記憶や推測よりも、配列が持つ正確な情報(.length)を信頼する方がはるかに安全です。

3. どんなサイズの配列にも対応できるようになります。(汎用性)
実際のプログラム開発では、配列のサイズが実行時まで決まらないことが多くあります。
ユーザーの入力やファイルから読み込んだデータの量によってサイズが変わる場合などです。
.lengthを使用することで、どのようなサイズの配列に対しても同じコードで適切に処理を行うことができます。

4. プログラムの意図を明確に伝えることができます。(可読性)
「5」とだけ書いてあると、なぜその数字なのか読み手には分かりません。
「numbers.length」と書かれていれば、「配列numbersの全体を処理しているのだな」と即座に理解できます。
意図が明確なコードは、後から読み返すときも、他の人が読むときも理解しやすくなります。

コラム

拡張for文

従来のfor文では、添字(インデックス)を使って「numbers[i]」のように要素にアクセスしていましたが
拡張for文では、このような複雑な手順を踏まずに、配列の中身を一つずつ自動的に取り出して変数に入れてくれるため
より直感的で分かりやすいコードを書くことができます。


つまり、従来の方法では「まず添字(インデックス)を指定して、そのインデックスを使って配列から値を取り出す
という2段階の作業が必要でしたが、
拡張for文では「配列から値を順番に取り出す」という1段階の作業だけで済むようになります。

拡張for文は、Java 5から導入された特別な構文で、配列の全ての要素を先頭から順番に処理したい場合に使用します。
「for-each文」とも呼ばれることがあります。

拡張for文の記載方法は
for (要素の型名 変数名 : 配列名) {
    // 各要素に対する処理
} 
になります。

サンプル:ForEachSample.java
  1. public class ForEachSample {
  2. public static void main(String[] args) {
  3. int[] numbers = new int[5];
  4. for (int i = 0; i < numbers.length; i++) {
  5. numbers[i] = i;
  6. }
  7. // 拡張for文
  8. for (int number : numbers) {
  9. System.out.println(number);
  10. }
  11. }
  12. }
実行結果
0
1
2
3
4

多次元配列

多次元配列とは何か
これまで学んできた配列は、ロッカーが一列に並んだような「一次元配列」でした。
しかし、プログラミングでは時として、もっと複雑なデータの構造を表現したい場面があります。
そんなときに活躍するのが「多次元配列」です。
多次元配列とは、配列の中にさらに配列を入れることで、表やマス目のような構造を作れる仕組みです。
最も一般的なのは「二次元配列」で、これはを持つ表のような形でデータを管理できます。

身近な例で理解する二次元配列
二次元配列を理解するために、身近な例を考えてみましょう。

例1:教室の座席表

学校の教室では、生徒の席が縦横に並んでいますよね。
たとえば5行6列の座席があるとすると、「3行目の4番目の席」のように、2つの数字を使って特定の席を指定できます。

例2:オセロ盤

オセロ盤は8×8のマス目になっています。
「上から3番目、左から5番目のマス」というように、縦と横の位置で特定のマスを表現できます。

例3:月間カレンダー

カレンダーも週(行)と曜日(列)で構成された表です。
「第3週の水曜日」のように、週番号と曜日で特定の日付を指定できます。

このように、2つの番号(添え字)を使って位置を特定するのが二次元配列の基本的な考え方です。

二次元配列の宣言と生成
二次元配列の宣言方法は、一次元配列に角括弧をもう一つ追加するだけです。
[][] 配列名;
そして生成は次のように行います。
配列名 = new[行数][列数];
実際のコードで見てみましょう。
サンプル:TwoDimensionalArraySample.java
  1. public class TwoDimensionalArraySample {
  2. public static void main(String[] args) {
  3. // 3行4列の二次元配列を宣言・生成
  4. int[][] table;
  5. table = new int[3][4];
  6. }
  7. }

これは「3行4列の表を作成する」という意味です。
教室に3つの列と4つの席がある座席表を用意するようなイメージです。

二次元配列への代入と参照
二次元配列では、2つの添え字を使って特定の位置にアクセスします。

配列名[行の添え字][列の添え字] =;  // 代入= 配列名[行の添え字][列の添え字];  // 参照 
重要なポイントは、一次元配列と同様に添え字は0から始まることです。

サンプル:TwoDimensionalArraySample.java
  1. public class TwoDimensionalArraySample {
  2. public static void main(String[] args) {
  3. // 3行4列の二次元配列を生成
  4. int[][] scores = new int[3][4];
  5.  
  6. // 各位置に値を代入
  7. scores[0][0] = 85; // 1行目1列目
  8. scores[0][1] = 90; // 1行目2列目
  9. scores[1][0] = 78; // 2行目1列目
  10. scores[2][3] = 95; // 3行目4列目
  11.  
  12. // 値を参照して出力
  13. System.out.println("1行目1列目の値: " + scores[0][0]);
  14. System.out.println("2行目1列目の値: " + scores[1][0]);
  15. System.out.println("3行目4列目の値: " + scores[2][3]);
  16. }
  17. }

実行結果
1行目1列目の値: 85
2行目1列目の値: 78
3行目4列目の値: 95 

二次元配列の初期化

二次元配列も一次元配列と同様に、さまざまな方法で初期化できます。

方法1:サイズだけ指定
int[][] table = new int[3][4];
この場合、すべての要素は自動的に0で初期化されます。

方法2:値を指定して初期化
  1. int[][] scores = {
  2. {80, 90, 85}, // 1行目
  3. {75, 88, 92}, // 2行目
  4. {95, 87, 90} // 3行目
  5. };

この書き方では、各行を中括弧で囲み、それらをさらに大きな中括弧で囲むことで、表の構造を視覚的に表現できます。

それでは、3人の生徒の3科目(国語、数学、英語)の成績を管理するプログラムを作ってみましょう。
サンプル:GradeManagement.java
  1. public class GradeManagement {
  2. public static void main(String[] args) {
  3. // 3人×3科目の成績表
  4. int[][] grades = {
  5. {85, 90, 78}, // 田中さんの成績
  6. {92, 85, 88}, // 佐藤さんの成績
  7. {78, 95, 90} // 鈴木さんの成績
  8. };
  9. // 3人の名前
  10. String[] students = {"田中", "佐藤", "鈴木"};
  11.  
  12. // 3個の科目名
  13. String[] subjects = {"国語", "数学", "英語"};
  14.  
  15. // 全生徒の全科目の成績を表示
  16. for (int i = 0; i < grades.length; i++) {
  17. System.out.println(students[i] + "さんの成績:");
  18. for (int j = 0; j < grades[i].length; j++) {
  19. System.out.println(" " + subjects[j] + ": " + grades[i][j] + "点");
  20. }
  21. System.out.println();
  22. }
  23. }
  24. }

実行結果
田中さんの成績:
  国語: 85点
  数学: 90点
  英語: 78点
 
佐藤さんの成績:
  国語: 92点
  数学: 85点
  英語: 88点
 
鈴木さんの成績:
  国語: 78点
  数学: 95点
  英語: 90点
 
二次元配列の.lengthの使い方

二次元配列でも.lengthを使用できますが、注意が必要です。

サンプル:TwoDimensionalArrayLengthSample.java
  1. public class TwoDimensionalArrayLengthSample {
  2. public static void main(String[] args) {
  3. int[][] table = new int[3][4];
  4.  
  5. System.out.println("行数: " + table.length);
  6. System.out.println("列数: " + table[0].length);
  7. }
  8. }
3
4
table.length行数を返し、table[0].length最初の行の列数を返します。これは「表全体の行数」と「特定の行の列数」を調べる方法です。

二次元配列と二重ループ

二次元配列のすべての要素を処理したい場合は、二重のfor文(ネストしたループ)を使用します。
  1. public class DoubleLoopSample {
  2. public static void main(String[] args) {
  3. int[][] matrix = {
  4. {1, 2, 3},
  5. {4, 5, 6},
  6. {7, 8, 9}
  7. };
  8.  
  9. // 全要素を順番に表示
  10. for (int i = 0; i < matrix.length; i++) { // 行のループ
  11. for (int j = 0; j < matrix[i].length; j++) { // 列のループ
  12. System.out.print(matrix[i][j] + " ");
  13. }
  14. System.out.println(); // 行が終わったら改行
  15. }
  16. }
  17. }

実行結果
1 2 3 
4 5 6 
7 8 9  

三次元配列とそれ以上
二次元配列をさらに発展させて、三次元配列やそれ以上の次元も作ることができます。

int[][][] cube = new int[3][3][3];  // 3×4×5の三次元配列 
三次元配列は、たとえば「ビルの階数×部屋の行×部屋の列」のような構造を表現するときに使用できます。
しかし、実際のプログラミングでは二次元配列が最も頻繁に使用され、三次元以上はそれほど一般的ではありません。

多次元配列は、表やマス目のような二次元的な構造を持つデータを効率的に管理できる強力な仕組みです。
一次元配列の概念を理解していれば、それを拡張した多次元配列も同様に理解できます。
重要なのは、各次元が何を表現しているのかを明確にイメージすることです。
教室の座席表やカレンダーのような身近な例を思い浮かべながら練習することで、多次元配列の概念をしっかりと身につけることができるでしょう。

ウィキ募集バナー