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

Java Java
スポンサーリンク

Javaの三次元配列の入門

三次元配列は「箱の中に箱があって、その中にまた箱がある」イメージです。二次元が「表(行×列)」なら、三次元は「層×行×列」。棚の段(層)ごとに、表が並んでいる感覚で捉えるとわかりやすいです。


三次元配列の基礎イメージ

  • 構造: 層・行・列の3つの軸で場所を指定する
  • 添字の順番: [層][行][列] が基本(0からスタート)
  • 用途の例: 3Dグリッド、時間で変わる画像フレーム、立方体データ、複数クラス×生徒×科目など

作り方(初期化)の3つの方法

1) サイズだけ決めてから値を入れる(いちばん基本)

int[][][] cube = new int[2][3][4]; // 2層・3行・4列

// 例:インデックスの合計を入れてみる
for (int z = 0; z < cube.length; z++) {           // 層
    for (int i = 0; i < cube[z].length; i++) {    // 行
        for (int j = 0; j < cube[z][i].length; j++) { // 列
            cube[z][i][j] = z + i + j;
        }
    }
}
Java
  • ポイント: length は階層ごとに違う可能性があるため、各段階で書く。

2) 中身も同時に書く(小さいデータ向き)

int[][][] data = {
    {   // 層0
        {1, 2, 3},      // 行0
        {4, 5, 6}       // 行1
    },
    {   // 層1
        {7, 8, 9},      // 行0
        {10, 11, 12}    // 行1
    }
};
Java
  • ポイント: 外側の {} が「層」。その中の {} が「行」。さらに中が「列」。

3) ジャグ(三次元版)を使う(層や行でサイズが違う)

int[][][] jag = new int[2][][];  // 層数だけ決める
jag[0] = new int[2][];           // 層0は2行
jag[0][0] = new int[]{1, 2};     // 行0は2列
jag[0][1] = new int[]{3};        // 行1は1列

jag[1] = new int[1][];           // 層1は1行
jag[1][0] = new int[]{4, 5, 6};  // 行0は3列
Java
  • ポイント: 行・列の長さが層ごとに異なるデータを自然に表現できる。

使い方(取り出し・操作・表示)

要素を取り出す

System.out.println(data[1][0][2]); // 層1・行0・列2 → 9
Java
  • ポイント: 添字はそれぞれ 0 から始まる。順序を間違えない。

すべての要素を表示(基本の三重ループ)

for (int z = 0; z < data.length; z++) {
    System.out.println("Layer " + z + ":");
    for (int i = 0; i < data[z].length; i++) {
        for (int j = 0; j < data[z][i].length; j++) {
            System.out.print(data[z][i][j] + " ");
        }
        System.out.println();
    }
    System.out.println("---");
}
Java
  • ポイント: 見やすくするために層ごとに区切りを入れる。

実践例題で理解を深める

例題1:3Dグリッドに座標の合計を入れて可視化

目的: 各セルに「層+行+列」を入れて、構造に慣れる。

public class GridSum {
    public static void main(String[] args) {
        int[][][] grid = new int[2][3][4];

        for (int z = 0; z < grid.length; z++) {
            for (int i = 0; i < grid[z].length; i++) {
                for (int j = 0; j < grid[z][i].length; j++) {
                    grid[z][i][j] = z + i + j;
                }
            }
        }

        for (int z = 0; z < grid.length; z++) {
            System.out.println("Layer " + z + ":");
            for (int i = 0; i < grid[z].length; i++) {
                for (int j = 0; j < grid[z][i].length; j++) {
                    System.out.print(grid[z][i][j] + " ");
                }
                System.out.println();
            }
            System.out.println("---");
        }
    }
}
Java
  • ポイント: 値の規則が単純だと、添字の対応を確認しやすい。

例題2:3D版の「時間×行×列」でフレームの平均を取る

目的: 時間方向(層)に並ぶ2Dデータの、各セルの平均を計算。

public class FrameAverage {
    public static void main(String[] args) {
        int frames = 3, rows = 2, cols = 3;
        int[][][] video = new int[frames][rows][cols];

        // 適当に値を入れる(例:frame*10 + row*5 + col)
        for (int t = 0; t < frames; t++) {
            for (int r = 0; r < rows; r++) {
                for (int c = 0; c < cols; c++) {
                    video[t][r][c] = t * 10 + r * 5 + c;
                }
            }
        }

        double[][] avg = new double[rows][cols]; // 各セルの時間平均

        for (int r = 0; r < rows; r++) {
            for (int c = 0; c < cols; c++) {
                int sum = 0;
                for (int t = 0; t < frames; t++) {
                    sum += video[t][r][c];
                }
                avg[r][c] = (double) sum / frames;
            }
        }

        // 平均の表示
        for (int r = 0; r < rows; r++) {
            for (int c = 0; c < cols; c++) {
                System.out.print(avg[r][c] + " ");
            }
            System.out.println();
        }
    }
}
Java
  • ポイント: 三次元から二次元へ「集約」する典型パターン。

例題3:ジャグ3Dで「層ごとに形が違う表」を扱う

目的: 現実のデータに合わせて、層ごとに行・列の数が異なる集合を安全に走査。

public class Jagged3D {
    public static void main(String[] args) {
        int[][][] jag = new int[2][][];

        jag[0] = new int[2][];
        jag[0][0] = new int[]{1, 2};
        jag[0][1] = new int[]{3};

        jag[1] = new int[1][];
        jag[1][0] = new int[]{4, 5, 6};

        for (int z = 0; z < jag.length; z++) {
            System.out.println("Layer " + z + ":");
            for (int i = 0; i < jag[z].length; i++) {
                for (int j = 0; j < jag[z][i].length; j++) {
                    System.out.print(jag[z][i][j] + " ");
                }
                System.out.println();
            }
            System.out.println("---");
        }
    }
}
Java
  • ポイント: 各段階で length を見て回すと範囲外を防げる。

よくあるつまずきと回避法

  • 添字の順番ミス:
    • 例: [行][列][層] と書いてしまうと意図とズレる。まず「層」を決めてから「行」「列」を選ぶ流れで統一。
  • 範囲外アクセス:
    • 対策: ループ条件は必ず array.length / array[z].length / array[z][i].length を使う。固定値は避ける。
  • ジャグ配列の未初期化:
    • 対策: new int[x][][] の後は、層・行ごとに new を忘れずに。
  • 見づらい出力:
    • 対策: 層ごとに区切り行やラベルを挟んで可読性を上げる。

便利ヘルパー:三次元配列をきれいに表示

public static void print3D(int[][][] a) {
    for (int z = 0; z < a.length; z++) {
        System.out.println("Layer " + z + ":");
        for (int i = 0; i < a[z].length; i++) {
            System.out.print("[ ");
            for (int j = 0; j < a[z][i].length; j++) {
                System.out.print(a[z][i][j] + (j < a[z][i].length - 1 ? ", " : ""));
            }
            System.out.println(" ]");
        }
        System.out.println("---");
    }
}
Java
  • ポイント: デバッグで「どこに何が入っているか」を素早く確認できる。

ミニ練習問題

  • 問題1: 3層・2行・3列の三次元配列を作り、値 = 層*100 + 行*10 + 列 を入れて全表示してください。
  • 問題2: 時系列データ(層=時間)から、各層の合計を計算して「層ごとの合計」を表示してください。
  • 問題3: ジャグ3Dで、層0は「2行(2列と1列)」、層1は「1行(3列)」にして、すべての要素の最大値を探してください。

解答と解説

問題1

3層・2行・3列の三次元配列を作り、値 = 層*100 + 行*10 + 列 を入れて全表示

解答コード

public class Practice1 {
    public static void main(String[] args) {
        int[][][] arr = new int[3][2][3]; // 3層・2行・3列

        // 値を代入
        for (int z = 0; z < arr.length; z++) {          // 層
            for (int i = 0; i < arr[z].length; i++) {   // 行
                for (int j = 0; j < arr[z][i].length; j++) { // 列
                    arr[z][i][j] = z * 100 + i * 10 + j;
                }
            }
        }

        // 表示
        for (int z = 0; z < arr.length; z++) {
            System.out.println("Layer " + z + ":");
            for (int i = 0; i < arr[z].length; i++) {
                for (int j = 0; j < arr[z][i].length; j++) {
                    System.out.print(arr[z][i][j] + " ");
                }
                System.out.println();
            }
            System.out.println("---");
        }
    }
}
Java

解説

  • z*100 + i*10 + j で「層・行・列」を数字に反映。
  • 出力例(Layer 0 の一部): Layer 0: 0 1 2 10 11 12 ---

問題2

時系列データ(層=時間)から、各層の合計を計算して「層ごとの合計」を表示

解答コード

public class Practice2 {
    public static void main(String[] args) {
        int[][][] data = {
            { {1, 2, 3}, {4, 5, 6} },   // 層0
            { {7, 8, 9}, {10, 11, 12} },// 層1
            { {13, 14, 15}, {16, 17, 18} } // 層2
        };

        for (int z = 0; z < data.length; z++) {
            int sum = 0;
            for (int i = 0; i < data[z].length; i++) {
                for (int j = 0; j < data[z][i].length; j++) {
                    sum += data[z][i][j];
                }
            }
            System.out.println("Layer " + z + " の合計: " + sum);
        }
    }
}
Java

解説

  • 外側ループで「層」を回す。
  • 内側二重ループで「行×列」を合計。
  • 出力例: Layer 0 の合計: 21 Layer 1 の合計: 57 Layer 2 の合計: 93

問題3

ジャグ3Dで、層0は「2行(2列と1列)」、層1は「1行(3列)」にして、すべての要素の最大値を探す

解答コード

public class Practice3 {
    public static void main(String[] args) {
        int[][][] jag = new int[2][][];

        jag[0] = new int[2][];
        jag[0][0] = new int[]{5, 12};   // 層0 行0
        jag[0][1] = new int[]{7};       // 層0 行1

        jag[1] = new int[1][];
        jag[1][0] = new int[]{20, 3, 15}; // 層1 行0

        int max = jag[0][0][0]; // 最初の値で初期化

        for (int z = 0; z < jag.length; z++) {
            for (int i = 0; i < jag[z].length; i++) {
                for (int j = 0; j < jag[z][i].length; j++) {
                    if (jag[z][i][j] > max) {
                        max = jag[z][i][j];
                    }
                }
            }
        }

        System.out.println("最大値: " + max);
    }
}
Java

解説

  • ジャグ配列は「層ごとに行・列のサイズが違う」。
  • length を毎回確認しながらループするのが安全。
  • 出力例: 最大値: 20

まとめ

  • 問題1 → 三重ループで「層・行・列」を意識。
  • 問題2 → 層ごとに合計を計算する典型パターン。
  • 問題3 → ジャグ配列の扱い方と「最大値探索」。
Java
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました