JavaRush /Java Blog /Random-JA /多次元配列

多次元配列

Random-JA グループに公開済み
多次元配列 - 1

Java の 1 次元配列とは何ですか?

配列は、同じタイプ (プリミティブまたは参照) の要素の順序付けされたセットです。配列 (主に 1 次元) に関する一般的な情報は、記事「Java の配列」およびJavaRushコースに記載されています。この記事では、要素が他の配列である配列について説明します。このような配列は多次元と呼ばれます。要素が他の配列である配列、つまり配列の配列を 2 次元と呼びます。すべての言語がこのように構造化された多次元配列を持っているわけではありませんが、Java ではこれが当てはまります。

Java 多次元配列、一般的な構文

一般に、Java の多次元配列は次のようになります。
Data_type[dimension1][dimension2][]..[dimensionN] array_name = new data_type[size1][size2].[sizeN];
ここで、 はData_type配列内の要素の型です。プリミティブまたは参照 (クラス) にすることができます。内側の括弧のペアの数がdimension配列の次元になります (この場合は - N)。 array_name— 配列名 size1...sizN— 配列の各次元の要素の数。多次元配列の宣言:
int[][] twoDimArray; //two-dimensional array
String[][][] threeDimArray; //three-dimensional array
double[][][][][] fiveDimArray; // five-dimensional array
おそらくこれはすべて非常に抽象的に見えるので、多次元配列 (2 次元と 3 次元) の具体的な表現に移りましょう。実際のところ、Java 開発者は 2 次元配列を使用することもありますが、3 次元配列を使用することはほとんどなく、さらに大きな配列を使用することは非常にまれです。遭遇しない可能性が高いです。

JavaRush コースの多次元配列

JavaRush では、「通常の」配列はJava 構文クエストのレベル 7から開始され、コースの後半では複数回出現します。コース全体を通じて、2 次元配列に関する問題 (またはその助けを借りて解決できる問題) に遭遇することがあります。2 次元配列は、特別セクション「Games on JavaRush」のゲーム エンジンでも使用されています。まだ行ったことがない場合は、ぜひ見て、ゲームを 1 ~ 2 つ作成してください。利用規約には詳細な手順が記載されており、プログラミング スキルの優れたトレーニングになります。3 次元配列は、ゲーム「スペース インベーダー」で見ることができます。これにより、アニメーション用のフレームのセットが指定されます (これらのフレームのそれぞれは 2 次元配列です)。JavaSyntax のクエストをすでに完了している場合、または Java プログラミングに自信がある場合は、この古典的なゲームの独自バージョンを作成してみてください。

Java の 2 次元配列とは何ですか?

Java の 2 次元配列は配列の配列です。つまり、各セルには配列への参照が含まれています。ただし、指定された行数 (1 番目の次元) と列数 (2 番目の次元) を持つテーブルの形式で表現する方がはるかに簡単です。すべての行に同じ数の要素がある 2 次元配列は、長方形と呼ばれます。

2 次元配列の宣言、作成、初期化

2 次元配列の宣言と作成の手順は、1 次元配列の場合とほぼ同じです。
int[][] twoDimArray = new int[3][4];
この配列には 3 行 4 列があります。長方形の 2 次元配列 (長方形でない場合もあります。詳しくは後述します) のサイズ、つまり要素の総数は、行数と列数を乗算することで決定できます。これで、デフォルト値で初期化 (埋められ) されました。つまりゼロです。必要な値を入力しましょう。
twoDimArray[0][0] = 5;//write the value 5 into the cell at the intersection of the zero row and zero column
twoDimArray[0][1] = 7; //write the value 7 into the cell at the intersection of the zero row and the first column
twoDimArray[0][2]  = 3;
twoDimArray[0][3] = 17;
twoDimArray[1][0] = 7;
twoDimArray[1][1] = 0;
twoDimArray[1][2] = 1;
twoDimArray[1][3] = 12;
twoDimArray[2][0] = 8;
twoDimArray[2][1] = 1;
twoDimArray[2][2] = 2;
twoDimArray[2][3] = 3;
1 次元配列と同様に、初期化手順をより速く実行できます。
int [][] twoDimArray = {{5,7,3,17}, {7,0,1,12}, {8,1,2,3}};
どちらの場合も、整数で埋められた 3 行 4 列の 2 次元配列が得られます。 多次元配列 - 2

2次元配列を画面上に表示する

この操作を実行する最も論理的な方法は、最初にゼロ行を要素ごとに出力し、次に 2 番目の行を出力するというように繰り返すことです。Java で 2 次元配列を出力する最も一般的な方法は、2 つのネストされたループを使用することです。
int [][] twoDimArray = {{5,7,3,17}, {7,0,1,12}, {8,1,2,3}};//declared an array and filled it with elements
for (int i = 0; i < 3; i++) {  //go through the lines
            for (int j = 0; j < 4; j++) {//go through the columns
                System.out.print(" " + twoDimArray[i][j] + " "); //output element
            }
            System.out.println();// line wrap for the visual preservation of the tabular form
        }

2次元配列の高速出力

2 次元配列の要素のリストを画面に表示する最も簡単な方法は、deepToStringクラスメソッドを使用することですArrays。例:
int[][] myArray = {{18,28,18},{28,45,90},{45,3,14}};
System.out.printLn(Arrays.deepToString(myArray));
プログラムの結果は次の出力になります: [[18, 28, 18], [28, 45, 90], [45, 3, 14]]

2次元配列の「長さ」

1 次元配列の長さ (つまり、配列内の要素の数) を取得するには、変数 を使用できますlength。つまり、配列を定義するとint a[] = {1,2,3}、演算はa.length3 を返します。しかし、同じ手順を 2 次元配列に適用するとどうなるでしょうか。
int [][] twoDimArray = {{5,7,3,17}, {7,0,1,12}, {8,1,2,3}};
System.out.println(twoDimArray.length);
出力: 3 したがって、この操作は配列内の行数を出力します。列数を取得するにはどうすればよいですか? 長方形の 2 次元配列 (つまり、すべての行が同じ長さである配列) を扱っている場合は、ゼロ要素 (本質的にはゼロ行) の代わりに、他の既存の要素の演算を適用できますtwoDimArray[0].length。Java では 2 次元配列は配列の配列であり、要素 0 はtwoDimArray[0]長さ 4 の配列であるため、これが可能です。これは自分で確認できます。

2 次元配列の使用例: チェッカーボード

2 次元配列を使用すると、たとえばゲーム、特にチェスなどの有限の 2 次元フィールドを作成できます。チェス盤を 2 次元配列として考えるのは簡単です。これにグラフィックを「添付」することもできますが、ここではシンボルを使用してチェス盤を定義し、それをコンソールに出力しましょう。 多次元配列 - 3チェス盤の左下の四角は黒く塗られ、次の四角はその上の四角と同様に白で塗りつぶされます。したがって、隣のセルに移動するたびに色が変わります。チェスのカラーリングを手動ではなくアルゴリズムを使用して設定するには、パリティ チェックを使用できます。行と列のインデックスの合計が偶数またはゼロの場合、セルは白になり、それ以外の場合は黒になります。このチェックでは、アルゴリズムで剰余演算子 % を使用します。ここではグラフィックスではなくシンボルを使用しているため、白いセルを文字W(白) で表し、黒いセルを文字B(黒) で表します。
//set the chessboard as a two-dimensional array
String [][] chessBoard = new String[8][8];
        for (int i = 0; i< chessBoard.length; i++) {
            for (int j = 0; j < chessBoard[0].length; j++) {
                if ((i + j) % 2 == 0) chessBoard[i][j] = "W";
                else chessBoard[i][j] = "B";
            }
        }
プログラムの出力は次のとおりです。 WBWBWBWBBWBWBWBWWBWBW BWBBWBWBWBWWBWBWBWBBW BWBWBWWBWBWBWBBWBWBWB W すべてが本物のチェス盤のようで、確認できます。 多次元配列 - 4ここで、セルに正しく番号を付けるメソッドを配列言語ではなく「チェス」言語で書いてみましょう。ボード上の左下のセルは A1 と呼ばれますが、この配列では ですchessBoard[7][0]。2 次元配列のインデックスの各ペアを、「チェス」に相当するものと関連付けてみましょう。これを行うには、「abcdefgh」と「87654321」の 2 つの線を使用します (簡単にするために逆の順序で、チェッカーボード 8 がゼロ列に対応するようにします)。
public static String chessBoardCoord(int a, int b) {
            String letters = "abcdefgh";
            String numbers = "87654321";
            if ((a > 7)|| (b>7)) return null; //if the number is outside the board, return the default value - null
            else return (Character.toString(letters.charAt(a)) + numbers.charAt(b)); /*charAt - a method with which we extract from the string the element under the passed number, here - under the numbers a and b. Character.toString - a method that converts the received character into a string */
        }
次に、次のメソッドを使用して、各セルに色だけでなく番号も表示してみましょう。chessBoardCoord
String [][] chessBoard = new String[8][8];
        for (int i = 0; i < chessBoard.length; i++) {
            for (int j = 0; j < chessBoard[0].length; j++) {
                if ((i + j) % 2 == 0) chessBoard[i][j] = "W" + chessBoardCoord(j,i);
                else chessBoard[i][j] = "B"+ chessBoardCoord(j,i);
            }
        }

            for (int i = 0; i < chessBoard.length; i++) {
                for (int j = 0; j < chessBoard[0].length; j++) {
                    System.out.print(" " + chessBoard[i][j] + " ");
                }
                System.out.println();
            }
プログラム出力: Wa8 Bb8 Wc8 Bd8 We8 Bf8 Wg8 Bh8 Ba7 Wb7 Bc7 Wd7 Be7 Wf7 Bg7 Wh7 Wa6 Bb6 Wc6 Bd6 We6 Bf6 Wg6 Bh6 Ba5 Wb5 Bc5 Wd5 Be5 Wf5 Bg5 Wh5 Wa4 Bb4 Wc4 Bd4 We4 Bf4 Wg4 Bh4 Ba3 Wb3 Bc3 Wd 3 Be3 Wf3 Bg3 Wh3 Wa2 Bb2 Wc2 Bd2 We2 Bf2 Wg2 Bh2 Ba1 Wb1 Bc1 Wd1 Be1 Wf1 Bg1 Wh1 ここで、We2e2 の番号が付いた白い正方形を意味します。

2 次元配列の使用例: 行列の乗算

注意!この例では、行列の基本的な知識が必要です。ここではそれらについてはほとんど説明しません。この情報は、行列演算を勉強したことはあっても、忘れてしまった人を対象としています。ただし、この知識はオープンソース、特にWikipedia の記事から収集できます。これは 2 次元配列を使用する良い例ですが、それを使用せずに先に進むこともできます。したがって、数学的な観点から見て理解できないと思われ、深く掘り下げたくない場合は、この例をスキップしてください。基本的な線形代数を学習したことがある場合は、長方形行列としての長方形配列について学習したことがあるかもしれません。 多次元配列 - 5ここで、a11、a12...aNN は数値です。図では、行列は長方形ではなく正方形です(行数は列数と等しいですが、常にそうとは限りません)。実生活では、このような行列に遭遇することはめったにありませんが、プログラミングやコンピューター サイエンスでは非常に一般的です。特に、コンピュータ グラフィックスやゲーム エンジンで使用されます。たとえば、回転行列を使用して、画面上のオブジェクトの任意の角度への回転をプログラムできます。2 次元空間では、回転行列は次のようになります。 多次元配列 - 6ここで、theta はオブジェクトを回転する必要がある角度です。同じ次元の行列は互いに加算でき、加算は要素ごとに行われます (同じインデックスを持つ要素を追加します)。しかし、行列の乗算の演算はあまり馴染みがありません。したがって、最初の行列の列数が 2 番目の行列の行数と一致する場合にのみ、行列を乗算して結果の行列を取得できます。結果の行列は、最初の行列と同じ行数、2 番目の行列と同じ数の列を持ちます。乗算は次のように実行されます。行列a[l][m]と を考えてみましょうb[m][n]。それらの乗算の結果として、行列 を取得する必要がありますc[l][n]。積行列の要素を取得するにはc[0][0]、最初の行列の 0 行の 0 要素と 2 番目の行列の 0 要素を乗算し、次に最初の行列の 1 行目の 1 要素と最初の要素を乗算する必要a[0][0]があります。 2 番目の行列の最初の列の値など、その後、結果として得られるすべての積が加算されます。

a[0][0]*b[0][0] + a[0][1]*b[1][0] + … + a[0][m-1]*b[m-1][0]
結果行列の最初の行の 2 番目の要素を取得するには、2 番目の行に対して同じ手順を実行します。

a[1][0]*b[0][0] + a[1][1]*b[0][1] + … + a[0][m-1]*b[m-1][0]
行の終わりまで続きます。次に、次の行に進み、行がなくなるまでこの手順を繰り返します。つまり、最初の行列の行と 2 番目の行列の列を乗算します。以下は行列乗算のコードです。行と列の数に関する上記の条件への準拠をチェックすることで、これを補うことができます。
//declaring two matrices
int [][] twoDimArray1 = {{1,0,0,0},{0,1,0,0},{0,0,0,0}};
int[][] twoDimArray2 = {{1,2,3},{1,1,1},{0,0,0},{2,1,0}};

//matrix multiplication process
int[][]twoDimArray3 = new int [twoDimArray1.length][twoDimArray2[0].length];
        for (int i=0; i<twoDimArray3[0].length; i++)
            for (int j=0; j<twoDimArray3.length; j++)
                for (int k=0; k<twoDimArray1[0].length; k++)
                              twoDimArray3[i][j] = twoDimArray3[i][j] + twoDimArray1[i][k] * twoDimArray2[k][j];

//output on display
        for (int i = 0; i < twoDimArray3.length; i++) {
            for (int j = 0; j < twoDimArray3[0].length; j++) {
                System.out.print(" " + twoDimArray3[i][j] + " ");
            }
            System.out.println();
        }
プログラムは次の結果を出力します: 1 2 3 1 1 1 0 0 0

非長方形の 2 次元配列

Java では 2 次元配列は配列の配列であるため、内部配列のそれぞれは異なる長さになる可能性があります。配列を作成する場合、指定できるのは行数のみであり、列数 (実際には、これらの同じ行の長さ) は指定できません。例を見てみましょう。
//declaring and creating an array, specifying only the number of rows
int [][] twoDimArray = new int[5][];

//initialize the array, filling it with arrays of different lengths
        twoDimArray[0] = new int[]{1, 2, 3, 4, 5};
        twoDimArray[1] = new int[]{1,2,3,4};
        twoDimArray[2] = new int[]{1,2,3};
        twoDimArray[3] = new int[]{1,2};
        twoDimArray[4] = new int[]{1};
//display the resulting non-rectangular two-dimensional array on the screen
        for (int i = 0; i < twoDimArray.length; i++) {
            for (int j = 0; j < twoDimArray[i].length; j++) {
                System.out.print(" " + twoDimArray[i][j] + " ");
            }
            System.out.println();
        }
プログラム出力: 1 2 3 4 5 1 2 3 4 1 2 3 1 2 1 したがって、配列の 0 行目には array が含まれ{1,2,3,4,5}、4 行目には array が含まれます{1}

Java の 3 次元配列

常識と Java 言語の論理に従って、3 次元配列は「配列の配列の配列」または「各要素が 2 次元配列である配列」と呼ぶことができます。さらに、これらの 2 次元配列は異なる場合もあります。例:
// create a three-dimensional array consisting of two two-dimensional arrays
int[][][] threeDimArr = new int[2][][];
//create the first 2D array of a 5x2 3D array
        threeDimArr[0] = new int[5][2];
//create a second 2D array of a 1x1 3D array
        threeDimArr[1] = new int[1][1];
しかし実際には、3 つの量すべてが一度に定義される 3 次元配列が使用されることが多く、これは長方形の 2 次元配列に似ています。 多次元配列 - 7すでに述べたように、3 次元以上の配列が使用されることはほとんどありません。ただし、3D 配列を使用して何か興味深いものをプログラムすることはできます。たとえば、立体駐車場。各フロアは 2 次元配列と考えることができ、駐車スペースは 3 次元配列の特定の要素と考えることができます。このような配列の要素は、スペースが空いている場合はbooleanfalse 、スペースが占有されている場合は trueの型で表すことができます。
//set a boolean three-dimensional array. This car park has 3 floors, each of which can accommodate 2x5 = 10 cars. By default, all cells are empty (false)
boolean[][][] parkingLot = new boolean[3][2][5];
//two cars arrived and parked on the ground floor in cell [1][0] and [1][3]
        parkingLot[0][1][0] = true;
        parkingLot[0][1][3] = true;

//Output the array to the console
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 2; j++) {
                for (int k = 0; k < 5; k++) {
                    System.out.print("arr[" + i + "][" + j + "][" + k + "] = " + parkingLot[i][j][k] + "\t");

                }
                System.out.println();
            }
        }

Java プログラマーの実際の作業における多次元配列

実際には、ほとんどの Java 開発者は多次元配列にあまり遭遇しません。ただし、このデータ構造が非常に適したタスクが数多くあります。

  1. 特定のアルゴリズムをチェックするためのテストと定数として行列を設定します。
  2. ニューラル ネットワークには多次元配列が使用されることがあります。
  3. 多次元配列はアーカイバーに適しています。
  4. 画像を扱う。

2 次元および 3 次元配列に関する興味深い問題

Java の多次元配列については十分に理解しているので、自信がある場合は、以下の問題のいくつかを解決してみてください。それらは簡単ではありませんが、興味深いものです。○×ゲーム。3x3 のフィールドを設定し、交代でプレイする 2 人のプレイヤーを作成します。最初、フィールドは空であり、空のフィールドのそれぞれに、最初のプレーヤーはクロスを置き、2番目のプレーヤーはゼロを置くことができます。勝者は、1 行、1 列、または斜めに配置された 3 つの十字または 3 つのゼロを最初に集めた人です。

他に何を読むべきか

初心者向けのJavaゲーム

ラングトンアリ。特定のフィールドがあり、セル (2 次元配列) に分割され、黒または白で塗りつぶされます (ランダム関数で設定できます)。「アリ」はいずれかのセルにランダムに出現し、各ステップで水平または垂直の 4 つの方向のいずれかに隣接するセルに移動できます。アリの移動ルール:
  • 黒い正方形上で、アリは左に 90 度回転し、セルの色を白に変えて、次の正方形に進みます。
  • 白い正方形上で、アリは右に 90 度回転してセルの色を黒に変え、次の正方形に進みます。
nアリの初期位置を指定して、ステップ番号での反復を計算するメソッドを作成します。フィールドには、0 と 1 をランダムに入力できます (または、チェス盤の例で行ったように、文字Wとで示されます)。Bさらに 2 つのパラメータも必要です。アリの水平位置と垂直位置、およびこのステップでの方向 (北、南、西、東) ですが、デフォルトではアリは北を向いています。3 次元配列を使用してルービック キューブをモデル化してみることができます。標準的なルービック キューブには 6 つの面があり、それぞれの面は色付きの正方形の 3 次元配列ですColor[][][] rubik = new Color[6][3][3]。ただし、ルービック キューブの実装は簡単な作業ではありません。

配列に関する役立つ資料

JavaRush の多くの記事は配列 (実際には配列の方がよく使用されるため、主に 1 次元のもの) に特化しています。それらに注意してください。
  1. Java の配列- 初心者向けの配列と例
  2. 配列に関するもの- 配列に関する優れた詳細な記事
  3. Arrays クラスとその使用法- この記事では、クラスのいくつかのメソッドについて説明します。Array
  4. 「配列」は、配列に特化した最初の JavaRush 講義です。
  5. null ではなく長さ 0 の配列を返す- 『Effective Programming』著者の Joshua Bloch が空の配列をより適切に返す方法について語ります
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION