CodeGym /コース /JAVA 25 SELF /ジャグ配列(Jagged Arrays)

ジャグ配列(Jagged Arrays)

JAVA 25 SELF
レベル 7 , レッスン 4
使用可能

1. ジャグ配列は2次元配列と異なる

ついに多くの人が「ジャグ配列」と呼ぶテーマに到達しました。英語では jagged arrays と言います。2次元配列と違い、ジャグ配列では各行の長さをバラバラにできます。たとえばマンション群があって、棟ごとに部屋数が違うようなものです — ある棟は5戸、別の棟は20戸、そして3つ目は1戸だけ、という具合です。

ジャグ配列とは、各要素自体が配列であり、かつ内側の配列(「サブ配列」とも呼ばれます)の長さがそれぞれ異なっていてよい配列のことです。

主な違い:

  • 2次元配列では各「行」(および各「列」)の要素数が同じです。 例: int[][] grid = new int[3][5]; — 常に3行で各行に5要素あります。
  • ジャグ配列では各行の長さを変えられます。 例: int[][] jagged = new int[3][]; — そして後で各行(サブ配列)をそれぞれ別々に初期化します。

見た目はこうなります:

2次元配列 (3x3):
┌───┬───┬───┐
│ 1 │ 2 │ 3 │
├───┼───┼───┤
│ 4 │ 5 │ 6 │
├───┼───┼───┤
│ 7 │ 8 │ 9 │
└───┴───┴───┘

ジャグ配列(長さが異なる):
┌───┬───┐
│ 1 │ 2 │
├───┼───┼───┬───┐
│ 3 │ 4 │ 5 │ 6 │
├───┼───┴───┴───┘
│ 7 │
└───┘

2. ジャグ配列の宣言と初期化の構文

ジャグ配列の宣言は、これまでの型と比べて何も怖くありません。二重の角かっこに怯える必要はありません:


int[][] jaggedArray = new int[3][];
ジャグ配列の宣言: 外側のサイズだけが指定され、内側の配列はまだ作られていない

これは、3要素からなる配列があり、その各要素が int の配列であることを意味します。ただし、まだ内側の配列は作られていません。よりよく理解するために、もう少し詳しく見てみましょう。

ジャグ配列を段階的に初期化する

ステップ1 — 外側(トップレベル)配列の作成:

int[][] jaggedArray = new int[3][];

これで「行」が3つありますが、どれもまだ null です。

ステップ2 — 内側の配列(サブ配列)の作成と長さの設定:
たとえば、1行目の長さを2、2行目を4、3行目を3にします:

jaggedArray[0] = new int[2]; // 1行目は2要素
jaggedArray[1] = new int[4]; // 2行目は4要素
jaggedArray[2] = new int[3]; // 3行目は3要素

ステップ3 — 値の代入:
内側の配列も普通の配列です。たとえば:

jaggedArray[0][0] = 1;
jaggedArray[0][1] = 2;

jaggedArray[1][0] = 3;
jaggedArray[1][1] = 4;
jaggedArray[1][2] = 5;
jaggedArray[1][3] = 6;

jaggedArray[2][0] = 7;
jaggedArray[2][1] = 8;
jaggedArray[2][2] = 9;

ジャグ配列の簡潔な初期化

値があらかじめ分かっているなら、その場で生成と初期化ができます:

int[][] jaggedArray = new int[][]
{
    new int[] { 1, 2 },
    new int[] { 3, 4, 5, 6 },
    new int[] { 7, 8, 9 }
};

あるいは、内側配列の型を省略してもう少し短く書けます:

int[][] jaggedArray = 
{
    { 1, 2 },
    { 3, 4, 5, 6 },
    { 7, 8, 9 }
};

3. ジャグ配列の走査と操作

ジャグ配列の走査は2次元配列と同じくらい簡単ですが、外側のループが行を、内側のループがその行の要素(長さが行ごとに異なる)を回る点に注意します:

for (int i = 0; i < jaggedArray.length; i++) 
{
    System.out.println("行 " + i + ":");
    for (int j = 0; j < jaggedArray[i].length; j++) 
    {
        System.out.print(jaggedArray[i][j] + " ");
    }
    System.out.println();
}

出力結果:

行 0:
1 2 
行 1:
3 4 5 6 
行 2:
7 8 9 

for-each を使えば、インデックスを気にせずに書けます:

for (int[] row : jaggedArray) 
{
    for (int value : row) 
    {
        System.out.print(value + " ");
    }
    System.out.println();
}

4. ジャグ配列の典型的な用途

どんなときに2次元配列よりジャグ配列が有用でしょうか?

  • 各ユーザーごとにデータ点の数が異なる場合(科目ごとの成績、購入履歴、コメントなど)。
  • データが三角形や段状の構造をしている場合(ピラミッド表示、パスカルの三角形など)。
  • メモリを節約したい場合。2次元配列ではすべての行が固定長ですが、ジャグ配列なら必要な分だけ確保できます。

身近な例: 学生の成績マネージャー

学生が3人いて、数学の課題ごとの点数が次のように違っているとします:

学生 点数
0 5, 4
1 3, 4, 4
2 5

このように配列を宣言します:

int[][] studentMarks = new int[3][];
studentMarks[0] = new int[] { 5, 4 };         // 1人目の学生 — 2件の点数
studentMarks[1] = new int[] { 3, 4, 4 };      // 2人目の学生 — 3件の点数
studentMarks[2] = new int[] { 5 };            // 3人目の学生 — 1件の点数

各学生の点数を出力します:

for (int i = 0; i < studentMarks.length; i++) 
{
    System.out.print("学生 " + i + ": ");
    for (int j = 0; j < studentMarks[i].length; j++) 
    {
        System.out.print(studentMarks[i][j] + " ");
    }
    System.out.println();
}

他の型でもジャグ配列

ジャグ配列は何にでもできます。文字列、さらに深い配列の配列、あなたのクラスのオブジェクトでも構いません。

例: 文字列配列

String[][] groups = {
    { "イワン", "ピョートル" },
    { "マリア", "アレクセイ", "セルゲイ" },
    { "ヴァシリーサ" }
};

5. 3次元配列と多次元配列

配列についてのもうひとつ興味深い事実です。2次元配列が作れるなら、3次元配列も作れるのではないでしょうか。

はい、任意の次元数の配列を作成できます。このような配列を多次元配列と呼びます。

多次元配列の宣言方法

必要な次元数だけ角かっこを並べて指定します:

int[][][] cube = new int[2][3][4]; // 2「層」、3行、4列
cube[0][1][2] = 99;

これは3次元配列です:

  • 第1軸に2要素、
  • 第2軸に3要素、
  • 第3軸に4要素。

この配列は、連続領域に詰め込まれた大きな「データのキューブ」です。

3次元配列の走査

要素へはすべての添字を指定してアクセスします:

for (int i = 0; i < cube.length; i++) 
{
    for (int j = 0; j < cube[i].length; j++) 
    {
        for (int k = 0; k < cube[i][j].length; k++) 
        {
            System.out.print(cube[i][j][k] + " ");
        }
        System.out.println();
    }
    System.out.println("---");
}
  • 添字は Java ではいつもどおり 0 から始まります。
  • この配列の要素総数は 2 × 3 × 4 = 24 です。

多次元配列の実用例

  • 2D — 表、チェス盤、画像。
  • 3D — コンピュータグラフィックスのボクセル、科学計算用データ(例: 時空間の各点の温度)。
  • 4D 以上 — あまり使われませんが、高度な数学、シミュレーション、機械学習などで登場します。

6. 多次元配列を扱う際の典型的な誤り

エラー1: 配列の範囲外アクセス

最もよくあるのは、存在しない要素にアクセスしようとすることです。例えば:

int[][] arr = new int[2][3];
arr[2][0] = 5; // エラー! インデックス2の行は存在しない(0 と 1 だけ)
arr[0][3] = 7; // エラー! インデックス3の列は存在しない(0, 1, 2 だけ)

このようなアクセスでは ArrayIndexOutOfBoundsException がスローされます。添字が有効範囲(0 から length - 1)内にあることを常に確認しましょう。

エラー2: ジャグ配列で内側の配列を未初期化のまま使う

ジャグ配列を作って内側の配列を初期化し忘れると、アクセス時に NullPointerException になります:

int[][] jagged = new int[3][];
jagged[0][0] = 5; // エラー! jagged[0] == null

まずは内側の配列を作成する必要があります: jagged[0] = new int[2];

エラー3: 配列の長さの使い方を誤る

matrix.length(行数)と matrix[0].length(列数)を取り違えるケースがよくあります。特にコピー、走査、列方向の合計などで発生します。

エラー4: すべての行が同じ長さだと思い込む

ジャグ配列では行の長さはバラバラです。matrix[i][j] にアクセスする場合は、j < matrix[i].length を確認しましょう。

エラー5: 添字の順序を取り違える

「先に行、次に列」という順序を取り違えることがあります。つまり matrix[行][列] の順です。逆ではありません。

コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION