配列とは

複数の値をまとめて扱う

プログラミングの世界では、大量のデータを処理することが頻繁に行われます。 例えば、住所録、表計算、楽曲リストなど、様々な例を思い浮かべることができるでしょう。 配列(array)と呼ばれるデータ構造を利用すれば、大量のデータを効率的に処理することができるようになります。

まずは、配列を使わず、複数の変数を使ったプログラムを見てみましょう。 VariablesSampleは5人の生徒のテストの得点を表示するだけの簡単なものです。

VariablesSample.java
class VariablesSample {
    public static void main(String[] args) {
        int ando = 64;
        int iwata = 75;
        int suzuki = 40;
        int tanaka = 92;
        int yamada = 58;

        System.out.println("1番の人の得点は" + ando + "点です。");
        System.out.println("2番の人の得点は" + iwata + "点です。");
        System.out.println("3番の人の得点は" + suzuki + "点です。");
        System.out.println("4番の人の得点は" + tanaka + "点です。");
        System.out.println("5番の人の得点は" + yamada + "点です。");
    }
}
VariablesSampleの実行結果
1番の人の得点は64点です。
2番の人の得点は75点です。
3番の人の得点は40点です。
4番の人の得点は92点です。
5番の人の得点は58点です。

ここでは生徒数がたったの5人ですが、後から追加されることも考えられます。 その場合、得点を出力するコードを各生徒毎に追加していかなければいけません。 そうなると、同じ様なコードがだらだらと記述され、場所を取って無駄が出てきます。 しかも、実際のプログラムはVariablesSampleよりもはるかに複雑なものです。 そうなると、変更箇所は一カ所では済まず、膨大な数になってくるでしょう。 データが増えるたびに骨の折れる作業を強いられては、たまったもんじゃありません。

そこで、いよいよ配列の出番ということになります。 配列は、同じ型の複数の値をまとめて記憶する機能を持っています。 イメージとしては、値を入れる箱が直線状に並んだものだと考えればよいでしょう。 個々の箱のことを要素(element)と呼びます。

図 8-1 : 基本型(プリミティブ型)の変数と配列

配列を準備する

配列を利用するには、次の2つのステップが必要になります。

  1. 配列変数を宣言する。
  2. 配列本体を生成して、その結果を配列変数に代入する。

まず1つ目のステップ、配列変数の宣言です。 配列変数(array variable)とは配列の本体を指す(参照する)変数のことです。 即ち、配列変数とは、参照(配列の本体が存在するメモリ上の場所の情報)が格納される特別な変数なのです。

構文 : 配列変数の宣言
型名[] 配列変数名;

例えばint型の要素からなる配列では、配列変数は次のように宣言します。

int[] a;

配列変数は配列型の変数とも呼ばれ、特に、この配列変数aはint[]型の変数と呼ばれることもあります。

尚、次のように宣言することもできますが、こちらはあまり使われません。

int a[];

基本型(プリミティブ型)の場合は、宣言したらすぐに値の代入などの操作が可能でしたが、配列の場合は事情が異なります。 配列変数というのは、配列の本体ではなくて、配列の本体を参照するための変数に過ぎないのです。 そのため、int型等の基本型に対して、配列型は参照型に分類されます。

2つ目のステップとして、配列変数の宣言とは別に、配列本体を生成します。

構文 : 配列本体の生成
配列変数名 = new 型名[要素数];

例えば、int型の要素からなる要素数5の配列本体を生成するには次のように記述します。

a = new int[5];

newという演算子を使って、int型の要素からなる要素数5の配列本体を生成して、その結果を配列変数aに代入しています。 これにより、配列変数aは配列本体を参照するようになるのです。

図 8-2を見て、配列変数の宣言と、配列本体の生成についてよく理解してください。

図 8-2 : 配列変数の宣言と配列本体の生成

配列変数の宣言と配列本体の生成が完了すると、配列の個々の要素に値を代入したり、値を取り出したりすることができるようになります。

配列を使うためには、配列変数を宣言して、配列本体を生成する必要がある。

既定値

ところで、図 8-2を見ると、配列の各要素には、始めから0という値が代入されています。 基本型の変数の場合は、値を代入する前に値を取り出そうとするとコンパイルエラーが発生していました。 しかし、配列の場合はnew演算子で配列本体を生成した時点で、各要素に自動的にある値が代入されることになっているのです。 このとき代入される値を既定値(default value)と呼びます。 要素の型によって既定値は決まっています。 それを表 8-1にまとめておきましょう。

表 8-1 : 既定値
既定値
byte (byte)0
short (short)0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'
boolean false
参照型 null

要素にアクセスする

では実際に、配列の個々の要素に値を代入したり、値を取り出したりする方法を見ていきましょう。 個々の要素は0から始まる添字インデックス : index)を使って、次のように表します。

構文 : 配列の要素
配列変数名[インデックス]

例えば、要素数を5と指定した場合、配列の要素はa[0], a[1], a[2], a[3], a[4]と表されます。 最初の要素のインデックスは0であり、最後は5-1=4であることに注意してください。 a[-1]やa[5]等、範囲外のインデックスを持つ要素を読み書きしようとすると実行時にエラーとなってしまいます。

配列の要素数がnなら、インデックスは0からn-1までとなる。

要素の型にint型を指定した場合、個々の要素にはint型の値を代入することができます。 配列の要素に値を代入するためには、代入演算子=を使います。 例えば、a[0]に64を代入するときは次のように記述します。

a[0] = 64;
図 8-3 : 配列の要素への値の代入

配列を使ってみる

それでは、配列を使って、VariablesSampleと同じ機能のプログラムを作ってみましょう。

ArraySample01.java
class ArraySample01 {
    public static void main(String[] args) {
        int[] a;
        a = new int[5];

        a[0] = 64;
        a[1] = 75;
        a[2] = 40;
        a[3] = 92;
        a[4] = 58;

        for(int i = 0; i < 5; i++){
            System.out.println((i + 1) + "番の人の得点は" + a[i] + "点です。");
        }
    }
}

ArraySample01の実行結果は、VariablesSampleと同じです。

ArraySample01の実行結果
1番の人の得点は64点です。
2番の人の得点は75点です。
3番の人の得点は40点です。
4番の人の得点は92点です。
5番の人の得点は58点です。

VariablesSampleと比べると、出力の部分でfor文を使っているため、非常にすっきりしたコードになっています。

        for(int i = 0; i < 5; i++){
            System.out.println((i + 1) + "番の人の得点は" + a[i] + "点です。");
        }

for文の中で使われる変数iの初期値が0であるため、「(i + 1)」として、表示される番号が1番から始まるように調整してあります。 配列の要素を指定するときは、a[i]のようにインデックスとして変数を使うことができます。

このプログラム中では、データの数が5個ですが、仮にデータを増やしたとしても、for文のループ本体を書き換える必要はありません。 配列とループを組み合わせることには、このようなメリットが有るのです。

ただし、for文の条件の「5」という数字はデータが増えるたびに書き換えてやる必要が有ります。 この部分も書き換えなくてすむ方法は後ほど解説します。

配列と繰り返し文を使うと、たくさんのデータを簡単に処理することができる。