CodeGym /コース /JAVA 25 SELF /配列入門

配列入門

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

1. 配列は要素のコンテナー

コンピューターが膨大な情報を処理できることは、きっと耳にしたことがあるでしょう。条件分岐(if-else)やループ(forwhile)は確かに役に立ちます。しかし、それだけでは不十分で、処理するデータをどこかに保存しなければなりません。

そのために Java(ほぼすべてのプログラミング言語と同様)には便利な仕組み、配列(Array)があります。表(テーブル)と呼ばれることもあります。

配列は、1 つではなく複数の値を保存できる特別なオブジェクトです。

Java の配列(Array)

以前、変数を「値を入れておける箱」に例えましたが、配列は内部が仕切られた箱に近いイメージです。「配列という箱」の各仕切り(セクション)には番号があります。番号付けはもちろん 0 から始まります…。

別のたとえにしましょう。平屋の家とマンション(多階建て)を比べてみます。平屋には 1 家族が住みますが、マンションは各戸に分かれています。平屋に住む家族へ手紙を送るなら、その家の住所だけを書きます。マンションの家族へ送るなら、家の住所に加えて部屋番号も書かなければなりません。

このように、配列変数は「マンション型の変数」です。1 つの値ではなく複数の値を保存できます。変数の中に複数の部屋(要素)があり、それぞれを番号(インデックス)で参照できます。

そのため、変数名の後ろに角括弧で作業対象の要素のインデックスを指定します。とても簡単です:


array[indeks] = znachenie;
インデックスを指定して配列の要素に値を代入する

ここで、array は配列変数の名前、indeks は配列内の要素番号(インデックス)、znachenie はその要素に格納したい値です。

ではまず、配列の作り方から確認しましょう。

2. Java における配列の作成

Java における配列の作成

仮に、プログラムでどこかに100 個の整数を保持する必要があるとします。おそらく、その用途には配列が適しています。では、どうやって作ればよいでしょうか?

1 つの整数だけを保存したいなら型は int で十分です。では、100 個の整数を保存したいなら、int 型の配列が必要でしょう。作成コードは次のとおりです:

int[] array = new int[100];
int の数値 100 個分の配列を作成

何が書かれているのか見ていきましょう。

すでに想像がつくかもしれませんが、等号の左側には array という名前の変数の宣言があり、その型は int[] です。型 int の後ろにある角括弧は、この「箱」には 1 つではなく複数の値を保存できることを示唆しています。

等号の右側には「オブジェクトの生成」(キーワード new)が書かれており、int 型の要素(部屋)を 100 個作るという意味です。これも難しくありません。

たとえば、実数を保存するための20 要素の配列を作りたい場合、作成コードは次のようになります:

double[] vals = new double[20];
double の配列(20 要素)の作成

配列の要素数は、配列のサイズまたは配列の長さと呼ばれます。多くの値を保存できることから、配列はコンテナーとも呼ばれます。

重要な事実: 配列コンテナーのサイズは作成後に変更できません

新しい配列を作ることはできますが、すでに作成した配列の長さを変えることはできません。

3. 配列要素の操作

配列要素の操作

配列の作り方は分かりました。では正しく操作するには?

基本的には通常の変数とほとんど同じですが、配列変数名の後には、操作対象の要素番号(インデックス)を必ず指定します。

配列の要素番号(インデックス)は常に 0 から始まります。 要素が 10 個ならインデックスは 0..9200 個なら 0..199 です。以降も同様です。

例:

int[] a = new int[10];	// int の 10 要素からなる配列を作成

a[2] = 4;				// インデックス 2 の要素に 4 を代入

a[7] = 9;				// インデックス 7 の要素に 9 を代入

a[9] = a[2] + a[5];		// インデックス 9 の要素に、要素 2(4 が入っている)と 	
                        // 要素 5(0 が入っている)の和を代入 

このコードを実行した後、メモリには次のように保存されます:

int 型配列の要素操作

配列の左側の列(灰色)は要素番号(インデックス)です。各要素には、書き込んだ値 494 が入っています。配列を作成した直後、要素は 0 で初期化されています。

重要: 配列の全要素は同じデータ型を持ちます。文字列の配列 String を作ったなら、要素に保存できるのは文字列だけです。配列のデータ型は作成時に決まります。作成後に、データ型も長さも変更できません。

4. メモリ上の配列

先ほどの図は少し正確さに欠けます。

配列(文字列の場合も同様)を作成するとき、メモリには 2 つの領域が確保されます。1 つは配列(コンテナー)自体を保存するため、もう 1 つはそのアドレスを保持する変数用です。修正した状況は次の図のとおりです:

メモリ上の配列

緑色は int 型の要素が 10 個の配列と、その配列のアドレス(参照)を保持する int[] 型の変数を表しています。

比較のため、青色は値 199 を保持する通常の int 型の変数です。

どこかで見たような、文字列のメモリ上での扱いに似ていませんか?

そのとおりです。文字列と同様に、「配列型の変数」は互いに代入できます:

int[] a = new int[10];		// int の 10 要素からなる配列を作成

a[2] = 4;					// インデックス 2 の要素に 4 を代入
a[7] = 9;					// インデックス 7 の要素に 9 を代入

int[] b = a;				// 変数 b に、変数 a が持つアドレスを保存する
                            // これで a と b は、メモリ上の同じ配列オブジェクトを指す

a[9] = b[2] + a[7];			// 配列オブジェクトのインデックス 9 の要素に、 
                            // 要素 2(4 が入っている)と 7(9 が入っている)の和を代入 

このとき、配列オブジェクト自体は元の場所にあり続け、ab は同じオブジェクトへのアドレス(参照)を保持します。次の図を見てください:

メモリ上の配列 2

5. 配列の扱いをもう少し詳しく

配列はどんな型からでも作成できます。型名の後に角括弧を書くだけです。一般形は次のとおりです:

tip[] imya = new tip[kolichestvo];
配列作成の標準形

ここで tip は配列(要素)の型、Imya は配列にアクセスするための変数名、kolichestvo は配列の要素数です。

上の例は、配列変数の作成と配列オブジェクトの作成を同時に行う標準形です。実際には、これは独立した 2 つの構文です。配列変数と配列オブジェクトは別々に作成できます:

tip[] imya;
imya = new tip[kolichestvo];
変数と配列を別々に作成

もう一つ重要なポイント

配列のインデックスや配列の要素数には、変数や式を使うこともできます。

例:

int n = 100;
int[] a = new int[n];			// 	n 要素の配列を作成

int n = 100;
int[] a = new int[n * 2 + 3];	// 	203 要素の配列を作成

int n = 100;
int[] a = new int[n];
a[n-1] = 2;					// a[99] = 2;
a[n-2] = 3;					// a[98] = 3;
a[n/5] = a[n-1] + a[n-2]	// a[20] = a[99] + a[98];

配列の範囲外アクセス

なお、配列に存在しないインデックスの要素にアクセスしようとすると(この例では 0..99 以外の整数すべて)、プログラムは ArrayIndexOutOfBoundsException(配列の範囲外インデックス)というエラーで異常終了します。

6. 配列の長さ

前の例で見たように、配列型の変数だけを先に作り、どこかの時点でその変数に配列オブジェクト(への参照)を代入することができます。次のように書くこともできます:

int[] array;			//	int[] 型の配列変数を作成
if (a < 10)				// 変数 a が 10 より小さければ
   array = new int[10];	// 要素数 10 の配列を作成
else					// それ以外なら
   array = new int[20];	// 要素数 20 の配列を作成 

では、この配列を以後どのように扱えばよいでしょうか。要素数はどうやって知るのでしょう?

配列には length という特別なプロパティ(変数)が用意されています。配列の長さは次の式で取得できます:

array.length;
プロパティ length で配列の長さを取得

ここで array は配列変数の名前、length は配列オブジェクトのプロパティ名です。length の値は変更できません。length 自体を別の変数に代入することはできますが、length に代入することはできません(コンパイルエラーになります)。

先ほどの例は次のように続けられます:

int[] array;			//	int[] 型の配列変数を作成
if (a < 10)				// 変数 a が 10 より小さければ
   array = new int[10];	// 要素数 10 の配列を作成
else					// それ以外なら
   array = new int[20];	// 要素数 20 の配列を作成 

for (int i = 0; i < array.length; i++)	// 配列の全要素を 0 から array.length − 1 まで反復
{
   System.out.println(array[i]);
}

7. Java の配列に関する事実

配列について、知っておくべき事実をまとめます:

  • 事実 1. 配列は多数の要素から成る。
  • 事実 2. 特定の要素へのアクセスは、その番号(インデックス)を指定して行う。
  • 事実 3. すべての要素は同一の型を持つ。
  • 事実 4. すべての要素の初期値は、数値なら 0、参照なら nullboolean 型なら false
  • 事実 5. String[] list は変数の宣言に過ぎず、コンテナー(配列オブジェクト)はまだ存在しない。操作するには配列(コンテナー)を作成してその変数に代入し、その後で使用する。下の例を参照。
  • 事実 6. 配列オブジェクト(コンテナー)を作成するときは、長さ(要素数)を指定する必要がある。書式は new TypeName[n] のようにする。
  • 事実 7. 配列の長さはプロパティ .length で取得できる。
  • 事実 8. 配列を作成した後は、要素の型も要素数も変更できない。
String s;				// s は null
String[] list;			// list は null

list = new String[10];	// 変数 list はオブジェクト(10 要素の文字列配列)への参照を保持する
int n = list.length;	// n は 10

list = new String[0];	// これで list は要素数 0 の配列を保持する 
                        // 配列自体はあるが、要素は保存できない

list = null;
System.out.println(list[1]); // プログラムエラーが発生し、異常終了する 
                            // list は空の参照(null)を保持している

list = new String[10];
System.out.println(list[10]);	// エラーが発生 — 配列の範囲外アクセス
//	list に 10 個の要素があるなら、許可されるインデックスは 0 1 2 3 4 5 6 7 8 9 — 合計 10 個 	
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION