多次元配列

9.8 多次元配列

 今までの配列は、配列の要素が一方向に一列に繋がっていました。このような配列を特に1次元配列といいます。
しかし、配列の各要素からも要素(の列)が伸びる2次元配列や3次元の方向にも要素を持つ3次元配列、あるいはそれ以上の次元にも要素を持つような配列を作ることも可能です。2次元配列が縦横に伸びる平面図形とすると、3次元配列はさらにそれぞれの要素から要素を参照するので、高さも持つ立方体のようなイメージであると表現することがあります。
このように、2次元以上の要素を持つ配列を多次元配列と呼びます。

9.8.1 2次元配列のイメージ

 通常の配列(1次元配列)と2次元配列をイメージにすると、次のようになります。

図 9.7.1 : カウンタ変数が0の時、インデックス0の要素へ代入


図 9.8.2 : 1次元配列のイメージ詳細


 2次元配列の場合は、次のようになります。

図 9.8.3 : 2次元配列のイメージ


図 9.8.4 : 2次元配列のイメージ詳細



 2次元以上の配列は、各要素からさらに要素が繋がっているようなイメージです。
 多次元配列は、「配列の配列」と呼ばれることもありますが、それは上の図 9.8.4を見ると分かるとおり、配列の要素が配列だからです。この例では、3つの要素を持つ2つの配列を束ねたものがint型の2次元配列変数kandaMansionであると言えます。

9.8.2 2次元配列の宣言

 2次元配列の宣言と初期化の基本構文は下記のようになります。

 1番目に指定した要素数が1次元方向(行)の要素数で、2番目に指定した要素数が2次元方向(列)の要素数です。例では、int型の2次元配列kandaMansionを宣言し、4行3列の記憶領域の確保を行っています。2次元配列も、要素の記憶領域の確保を行うと同時に規定値での初期化がなされます。int型の規定値は0なので、それぞれの要素は0で初期化されています。

図 9.8.5 : 2次元配列のイメージ詳細


 配列は、2次元、3次元、4次元、6次元、と複雑なものを作ることができますが、一般的には2次元配列まで使いこなせれば十分です。そのため、このテキストでは2次元配列のみに絞って学習します。

9.8.3 二重ループと2次元配列を組み合わせて値の代入と出力を行うプログラム

 このプログラムは、九九の全ての答えを段毎に表示するものです。このプログラムの作成を通して、二重ループと2次元配列を組み合わせて値の代入と出力を行う仕組みを理解しましょう。
 ネストしたfor文と多次元配列は、プログラムを作る上でとても良い組み合わせになります。ひとつひとつの流れを理解しながら進めましょう。

① ソース・フォルダー      :myproj_intro/src
② パッケージ          :jp.co.f1.intro.ch9
③ 名前             :TwoDimensionArrayWithKuku
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる

➢ TwoDimensionArrayWithKuku.java

package jp.co.f1.intro.ch9;

public class TwoDimensionArrayWithKuku {

	public static void main(String[] args) {

		// 九九の答えを管理する為の2次元配列の宣言
		int[][] kuku = new int[9][9];

		for(int dan = 0; dan < 9; dan++) {
			for(int i = 0; i < 9; i++) {
				kuku[dan][i] = (dan + 1) * (i + 1);
			}
		}

		for(int dan = 0; dan < 9; dan++) {
			System.out.print((dan + 1) + "の段 : ");
			for(int i = 0; i < 9; i++) {
				System.out.print(kuku[dan][i] + "\t");
			}
			System.out.println();
		}

	}
}

実行結果

解説

 二重のループ文を使うと、2次元配列の全ての要素をカウンタ変数を使って操作できます。
 先に、このプログラムの大まかな流れを解説します。
 8行目で九九の全ての解答を管理するint型の2次元配列変数kukuを作成します。
   8: int[][] kuku = new int[9][9];

 そして、10~14行目の二重for文で配列変数kukuに全ての九九の解答を格納します。
   10: for(int dan = 0; dan < 9; dan++) {
   11:    for(int i = 0; i < 9; i++) {
   12:          kuku[dan][i] = (dan + 1) * (i + 1);
   13:    }
   14: }

 16~22行目の二重for文では、九九の解答が格納されている配列変数の全ての要素を表示させます。
   16: for(int dan = 0; dan < 9; dan++) {
   17:    System.out.print((dan + 1) + "の段 : ");
   18:    for(int i = 0; i < 9; i++) {
   19:          System.out.print(kuku[dan][i] + "\t");
   20:    }
   21:    System.out.println();
   22: }

 このように、TwoDimensionArrayWithKuku.javaは1つの2次元配列の変数と2つの二重for文を利用して作成されています。

 では、このプログラムの詳しい動きを追ってみましょう。まず、8行目で行なう配列変数の宣言と記憶領域の確保をイメージにした図 9.8.6を見て下さい。2次元配列には、インデックスが2つあります。これは、行と列のある「表」のようにできていると考えると分かりやすいと思います。

図 9.8.6 : 2次元配列の宣言と要素の作成(一部)


 10~14行目では、二重ループのfor文を使って8行目で作成した2次元配列kukuのそれぞれの要素に九九の解答を代入しています。
 カウンタ変数danとカウンタ変数iは、そのままでは要素のインデックスとして利用されています。さらに、それぞれに1を足すことで、外側のカウンタ変数danは段の数を表し、内側のカウンタ変数iは掛ける数を表しています。下の表のように、配列変数kukuに対する全ての値の代入を二重ループで行っています。

 次に、2つ目の二重for文である16~22行目を見てみましょう。ここでは、外側のfor文の内部処理である17行目で段の数を表示し、内側のfor文の内部処理である19行目で配列変数kukuの要素を表示させています。
   16: for(int dan = 0; dan < 9; dan++) {
   17:    System.out.print((dan + 1) + "の段 : ");
   18:    for(int i = 0; i < 9; i++) {
   19:         System.out.print(kuku[dan][i] + "\t");
   20:    }
   21:    System.out.println();
   22: }

 16行目から外側のfor文に入り、int型の変数danの宣言と初期化を行い、条件を満たしているので17行目からの内部処理に移ります。
   16: for(int dan = 0; dan < 9; dan++) {

 17行目では、「1の段 : 」と表示されます。
   17: System.out.print((dan + 1) + "の段 : ");

 18行目で内側のfor文に入り、変数iの宣言と初期化を行い、条件式を満たしているので内側のfor文の内部処理である19行目が実行されます。
   18: for(int i = 0; i < 9; i++) {

 19行目では、配列変数kukuの要素を表示させる文です。内側のfor文は9回繰り返されるので、ここで1の段の全ての解答が表示されます。
   19: System.out.print(kuku[dan][i] + "\t");

 内側のfor文を抜けると、外側のfor文の内部処理の最後の行の21行目が実行され、改行されます。カウンタ変数danがインクリメントされ、外側のfor文の最初に戻ります。
   21: System.out.println();

 このようにして、全ての九九の答えを表示させています。処理の流れは、次の図 9.8.1も参考にして下さい。


表 9.8.1 : カウンタ変数の値の変化と内部処理


9.8.4 多次元配列の要素の初期化

 多次元配列も、宣言と同時に任意の値で初期化することができます。
 2次元配列では、下の書式のように「{ }」を二重にし、「{ }」の間をコンマ「 , 」で区切り、初期化します。さらに、3次元配列になれば「{ }」は三重に囲い、4次元になれば四重というようにネストが深くなっていきます。

9.8.5 2次元配列を初期化するプログラム

 2次元配列を初期化し値を出力するプログラムを作成し、結果を確認します。

① ソース・フォルダー      :myproj_intro/src
② パッケージ          :jp.co.f1.intro.ch9
③ 名前             :TwoDimensionArrayInitializer
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる

➢ TwoDimensionArrayInitializer.java

package jp.co.f1.intro.ch9;

public class TwoDimensionArrayInitializer {

	public static void main(String[] args) {

		// int型の2次元配列の宣言と要素の初期化
		int[][] intArray = {
				{50,150,250},
				{300,200,100}
		};

		for(int i = 0; i < intArray.length; i++){
			for(int j = 0; j < intArray[i].length; j++){
				System.out.println("intArray["+i+"]["+j+"]の値:" + intArray[i][j]);
			}
			System.out.println();
		}

	}

}

実行結果

解説

 8~11行目は、int型の2次元配列変数intArrayを宣言し、要素の記憶領域の確保と同時に初期化を行っています。これをイメージにすると、図 9.8.7のようにになります。
   8: int[][] intArray = {
   9:        {50,150,250},
   10:        {300,200,100}
   11: };

 また、8~11行目は、下記のように書き換えることもできます。


図 9.8.7 : 2次元配列の宣言と初期化


 13~18行目は、二重のfor文で、2次元配列変数intArrayの値を全て表示させています。内部処理が行なわれる順序は、表 9.8.2を参照して下さい。
 13行目の外側のfor文の条件式にあるintArray.lengthの値は2になります。int型の2次元配列変数intArrayは、int型の配列を2つ持っている変数であると言えるからです。図 9.8.7も確認してみて下さい。
 14行目のintArray[i]は、それぞれの配列の長さ(要素の数)を指しています。iが0の場合はintArray[0]になりますから、intArray[0]が参照している要素は3つ、つまりintArray[i].lengthの値は3となります。iが1の場合はintArray[1]になりますから、intArray[1]が参照している要素は3つ、つまりintArray[i].lengthの値は3となります。
 配列が要素となっているのが多次元配列です。配列変数の構造がどうなっているのかをもう一度図で確認してみて下さい。
   13: for(int i = 0; i < intArray.length; i++){
   14:    for(int j = 0; j < intArray[i].length; j++){
   15:          System.out.println("intArray["+i+"]["+j+"]の値:" + intArray[i][j]);
   16:    }
   17:    System.out.println();
   18: }

表 9.8.2 : カウンタ変数の値の変化と内部処理




NEXT>> 9.9 本章のまとめ