Java | 3次元配列(配列の配列の配列)

Java Java
スポンサーリンク

3次元配列は最初ちょっと取っつきにくいですが、イメージを押さえれば簡単です。ここでは「何か」「どう書くか」「よくある使い方」「練習問題(解答付き)」まで、丁寧に説明します。


まずはイメージ:立方体(層 × 行 × 列)

  • 2次元配列が「表(行 × 列)」なら、3次元配列は「層(layer) が積み重なった表」のイメージです。
  • 例えば int[][][] aa[層][行][列] の形で添字を使います。
  • 視覚化するとこう:
layer 0 (a[0]):       layer 1 (a[1]):       layer 2 (a[2]):
+---+---+---+         +---+---+---+         +---+---+---+
|0,0|0,1|0,2|         |0,0|0,1|0,2|         |0,0|0,1|0,2|
+---+---+---+         +---+---+---+         +---+---+---+
|1,0|1,1|1,2|         |1,0|1,1|1,2|         |1,0|1,1|1,2|
+---+---+---+         +---+---+---+         +---+---+---+

ここで a[2][1][2] は「層2の行1の列2」を意味します。


宣言・初期化パターン

1) 宣言と同時にリテラルで初期化(分かりやすい)

int[][][] cube = {
    { {1,2,3}, {4,5,6} },    // layer 0 : 2行3列
    { {7,8,9}, {10,11,12} }  // layer 1 : 2行3列
};
Java

この例は 2層 × 2行 × 3列 の配列です。

2) new でサイズを指定して後で代入

int[][][] cube = new int[3][4][5]; // 3層、各層は4行、各行は5列 (全要素は0で初期化)
cube[0][0][0] = 42;
Java

3) 各層・各行の長さを変える(ジャグな 3D 配列)

int[][][] jagged = new int[2][][]; // 層数だけ指定
jagged[0] = new int[1][];          // 層0は行数1
jagged[0][0] = new int[2];         // その行は列数2
jagged[1] = new int[3][];          // 層1は行数3
jagged[1][0] = new int[1];
jagged[1][1] = new int[2];
jagged[1][2] = new int[3];
Java

→ 各層・行で長さが自由に異なる構造にできます。


要素の参照(添字の順序)

  • a[layer][row][col] の順。
  • 添字はすべて 0始まり
  • 範囲外アクセスは ArrayIndexOutOfBoundsException を投げるので注意。

中身を処理する典型パターン:三重ループ

for (int l = 0; l < a.length; l++) {            // 層ループ
    for (int r = 0; r < a[l].length; r++) {     // 行ループ(層 l の行数)
        for (int c = 0; c < a[l][r].length; c++) { // 列ループ(その行の列数)
            System.out.println("a[" + l + "][" + r + "][" + c + "] = " + a[l][r][c]);
        }
    }
}
Java

ポイント:ジャグ配列にも対応するため、a[l].lengtha[l][r].length を使う。


実用例(よくあるユースケース)

  1. ボクセル(3D グリッド)データ:3D マップ・迷路・ゲームのブロック配置
  2. 時系列付きの 2D データ:時間(層) × 行 × 列(例:毎日の温度マップ)
  3. RGB 画像(別の表現)int[高さ][幅][3](ただし一般的には int[高さ][幅] に色をまとめる方が多い)
  4. 複数フレームの 2D データ:動画フレーム保存など(frame × y × x)

例題(解説付き)

例題A — 3層の立方体を初期化して全部表示

問題:3層、各層2行3列の配列を作り、layer*100 + row*10 + col の値で初期化して全要素を表示せよ。

public class ExampleA {
    public static void main(String[] args) {
        int[][][] cube = new int[3][2][3]; // 3層, 2行, 3列

        // 初期化
        for (int l = 0; l < cube.length; l++) {
            for (int r = 0; r < cube[l].length; r++) {
                for (int c = 0; c < cube[l][r].length; c++) {
                    cube[l][r][c] = l * 100 + r * 10 + c;
                }
            }
        }

        // 表示(層ごとに見やすく)
        for (int l = 0; l < cube.length; l++) {
            System.out.println("Layer " + l);
            for (int r = 0; r < cube[l].length; r++) {
                for (int c = 0; c < cube[l][r].length; c++) {
                    System.out.print(cube[l][r][c] + " ");
                }
                System.out.println();
            }
            System.out.println("----------");
        }
    }
}
Java

出力例

Layer 0
0 1 2
10 11 12
----------
Layer 1
100 101 102
110 111 112
----------
Layer 2
200 201 202
210 211 212
----------

例題B — 各層の合計を計算する

問題:上の cube について、各層(layer)の合計を求めよ。

for (int l = 0; l < cube.length; l++) {
    int layerSum = 0;
    for (int r = 0; r < cube[l].length; r++) {
        for (int c = 0; c < cube[l][r].length; c++) {
            layerSum += cube[l][r][c];
        }
    }
    System.out.println("Layer " + l + " sum = " + layerSum);
}
Java

例題C — ジャグな 3D 配列の処理

int[][][] jag = {
    { {1,2}, {3} },       // layer 0 : row0 has 2 cols, row1 has 1 col
    { {4,5,6} }           // layer 1 : row0 has 3 cols
};

// すべて合計
int total = 0;
for (int l = 0; l < jag.length; l++) {
    for (int r = 0; r < jag[l].length; r++) {
        for (int c = 0; c < jag[l][r].length; c++) {
            total += jag[l][r][c];
        }
    }
}
System.out.println("Total = " + total);
Java

(出力 Total = 1+2+3+4+5+6 = 21


可視化(簡単な ASCII 表示)

3次元配列は「層ごとに 2次元表を表示」すると見やすいです。先ほどの例題Aの表示は既に層表示になっています。さらに見やすくするなら、各層の上に罫線を引くメソッドを作ると良いです(2次元の ASCII 表示メソッドを層ループで呼ぶだけで OK)。


よくあるつまずきポイントと対策

  • 添字の順序を間違えるlayer, row, col の順で常に考える。
  • 範囲外アクセスa.length(層数)、a[l].length(その層の行数)、a[l][r].length(その行の列数)を使う。
  • ジャグ配列で a[l][r]null の可能性new していない行にアクセスすると NullPointerException になる。初期化漏れに注意。
  • 可読性 → 三重ループはネストが深いので、処理はメソッド化(例:sumLayer(a, l))すると読みやすくなる。

練習問題(初心者向け) — 解答付き

問1

int[][][] a = new int[2][2][2]; を作ったとき、全要素を 1 に設定するコードを書け。

for (int l = 0; l < a.length; l++)
  for (int r = 0; r < a[l].length; r++)
    for (int c = 0; c < a[l][r].length; c++)
      a[l][r][c] = 1;
Java

問2

int[][][] b = { { {1,2}, {3,4} }, { {5,6}, {7,8} } };b[1][0][1] の値は?

6(層1、行0、列1)

問3

3層×3行×3列の立方体 int[][][] v = new int[3][3][3]; に、v[l][r][c] = l + r + c; と入れたとき、v[2][1][0] の値は?

2 + 1 + 0 = 3

問4(少し応用)

各層の中で最大値を求めて、int[] maxPerLayer に格納するコードを書け。

答(サンプル)

int[][][] a = ...;
int[] maxPerLayer = new int[a.length];
for (int l = 0; l < a.length; l++) {
    int max = Integer.MIN_VALUE;
    for (int r = 0; r < a[l].length; r++) {
        for (int c = 0; c < a[l][r].length; c++) {
            if (a[l][r][c] > max) max = a[l][r][c];
        }
    }
    maxPerLayer[l] = max;
}
Java

問5(チャレンジ)

3D 配列を入力(層数、行数、列数、要素)から作り、各層の平均を計算するコンソールアプリを書け。
(ヒント:Scanner を使い、三重ループで合計と要素数を数える)


次のステップ(オススメ)

  • 3次元配列で 探索アルゴリズム(BFS/DFS) を試すと面白い(迷路/ボクセル探索)。
  • ArrayList を使って「動的な3次元構造」を作る練習(ArrayList<ArrayList<ArrayList<Integer>>>)。
  • 3次元配列のデータをファイルに保存・読み込みして、実際のデータで試す。
Java
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました