多次元配列(2次元配列)をやさしく説明する
イメージ:1次元配列は「一列のロッカー」。
2次元配列は「ロッカーの列が複数ある棚(行と列)」です。num[行][列] と考えるとわかりやすいです。行が外側、列が内側。
宣言・作成・代入・参照(基本)
// 宣言だけ(まだメモリは確保されない)
int[][] table;
// 宣言と作成(外側:2行、内側:3列)
int[][] table = new int[2][3];
// table は次のような箱(初期値は 0)
// table[0][0], table[0][1], table[0][2]
// table[1][0], table[1][1], table[1][2]
// 値を代入
table[0][0] = 10;
table[0][1] = 20;
table[0][2] = 30;
table[1][0] = 40;
table[1][1] = 50;
table[1][2] = 60;
// 参照
int x = table[1][2]; // 60 が入る
Java「内側の長さが違う(不揃い = jagged)」配列
Java では各行ごとに内側配列の長さを変えられます。
int[][] jagged = new int[3][]; // 外側は3行だが内側は未指定
jagged[0] = new int[2]; // 0行目は長さ2
jagged[1] = new int[4]; // 1行目は長さ4
jagged[2] = new int[1]; // 2行目は長さ1
Java表形式でない、行ごとに要素数が違うデータ(例:クラスごとに生徒数が違う)に便利。
値を一気に初期化する書き方
int[][] a = {
{1, 2, 3},
{4, 5, 6}
};
Java上と同じく a[0][1] == 2 になります。
要素を走査する:ネストした for(基本パターン)
for (int i = 0; i < table.length; i++) { // 行(外側)
for (int j = 0; j < table[i].length; j++) { // 列(内側)
System.out.print(table[i][j] + " ");
}
System.out.println();
}
Java拡張for(for-each)でもループできます:
for (int[] row : table) {
for (int v : row) {
System.out.print(v + " ");
}
System.out.println();
}
Java例題 1 — 基本:2×3 の表を作って表示する
public class Ex1 {
public static void main(String[] args) {
int[][] table = {
{10, 20, 30},
{40, 50, 60}
};
for (int i = 0; i < table.length; i++) {
for (int j = 0; j < table[i].length; j++) {
System.out.print(table[i][j] + "\t");
}
System.out.println();
}
}
}
Java出力:
10 20 30
40 50 60
例題 2 — 実践:各行の合計と平均を計算する(実用的)
public class RowSumAvg {
public static void main(String[] args) {
int[][] scores = {
{78, 64, 59},
{58, 92, 82}
};
for (int i = 0; i < scores.length; i++) {
int sum = 0;
for (int j = 0; j < scores[i].length; j++) {
sum += scores[i][j];
}
double avg = sum / (double)scores[i].length;
System.out.printf("行 %d の合計 = %d, 平均 = %.2f%n", i, sum, avg);
}
}
}
Java出力例:
行 0 の合計 = 201, 平均 = 67.00
行 1 の合計 = 232, 平均 = 77.33
例題 3 — jagged(行ごとに人数が違うクラスの平均)
public class Classroom {
public static void main(String[] args) {
int[][] classes = new int[3][];
classes[0] = new int[] {70, 80}; // クラス0は2人
classes[1] = new int[] {60, 65, 70}; // クラス1は3人
classes[2] = new int[] {90}; // クラス2は1人
for (int i = 0; i < classes.length; i++) {
int sum = 0;
for (int s : classes[i]) sum += s;
System.out.printf("クラス %d 平均=%.1f%n", i, sum / (double)classes[i].length);
}
}
}
Java出力:
クラス 0 平均=75.0
クラス 1 平均=65.0
クラス 2 平均=90.0
よくあるつまづきポイント(初心者向け注意)
int[][] a = new int[2][];のとき、a[0][0]にすぐアクセスすると NullPointerException(内側が null のため)。内側配列をnewするのを忘れずに。a.lengthは「外側の要素数(行数)」、a[i].lengthが「その行の列数」。行ごとにa[i].lengthを確認すると安全。int[] arr[];のようにも宣言できるが、読みづらいのでint[][] arr;を推奨。- 初期値:数値型は
0、参照型はnull、boolean はfalse。
練習問題
int[][] a = new int[3][2];を作り、全要素に1,2,3,...と順に代入して出力するプログラムを作りなさい。- 3×3 の行列
matrixを初期化し、対角要素(i==j)の合計を求めよ。 - jagged 配列を作り、各行の長さを表示するコードを書け。
- 2次元配列を受け取り、その配列を転置(行と列を入れ替える)して返すメソッドを書け(正方行列に限定して良い)。
- ユーザー入力で
m行n列の配列を作り、値を入力して各列の合計を表示する簡単なコンソールアプリを書け。
練習問題の解答
int[][] a = new int[3][2];
int v = 1;
for (int i=0;i<a.length;i++){
for (int j=0;j<a[i].length;j++){
a[i][j]=v++;
System.out.print(a[i][j]+" ");
}
System.out.println();
}
Javaint[][] matrix = {
{1,2,3},
{4,5,6},
{7,8,9}
};
int sum = 0;
for (int i=0;i<3;i++) sum += matrix[i][i];
System.out.println("対角和 = " + sum); // 15
Javaint[][] jag = {
{1,2},
{3,4,5},
{6}
};
for (int i=0;i<jag.length;i++){
System.out.println("行 " + i + " の長さ = " + jag[i].length);
}
Javapublic static int[][] transpose(int[][] a){
int n = a.length; // 正方行列と仮定
int[][] b = new int[n][n];
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
b[j][i] = a[i][j];
}
}
return b;
}
Java5.(ヒント:Scanner を使って m,n を読み取り、二重ループで入力→列ごとに合計を算出)
まとめ(初心者が覚えるべき最重要ポイント)
int[][] arrは「配列の要素がさらに配列」 →arr[行][列]でアクセス。arr.lengthは外側の要素数(行数)。行ごとにarr[i].lengthを使う。- 内側の長さが違う(jagged)配列が作れる。
- 二重ループ(ネストfor)で処理するのが基本。拡張 for も便利。
- 内側配列が
nullになっている場合があるので注意(newを忘れない)。
