配列
配列①
同一型の変数の集まりは、バラバラでなく、ひとまとめにすると扱いやすくなります。そこで、配列が有効になります。
配列
「テストの点数」を集計するプログラムを作って学んでいきましょう。以下に示すのは、5人の点数を読み込んで合計と平均を求めるプログラムになります。
//PointSumAve.java
//点数を読み込んで合計点、平均点を表示
import java.util.Scanner;
public class PointSumAve {
public static void main(String[] args){
Scanner stdIn = new Scanner(System.in);
int sum = 0;
System.out.println("5人の点数を入力してください。");
System.out.print("1番の点数:");
int akane = stdIn.nextInt();
sum += akane;
System.out.print("2番の点数:");
int baba = stdIn.nextInt();
sum += baba;
System.out.print("3番の点数:");
int cocone = stdIn.nextInt();
sum += cocone;
System.out.print("4番の点数:");
int docomo = stdIn.nextInt();
sum += docomo;
System.out.print("5番の点数:");
int eita = stdIn.nextInt();
sum += eita;
System.out.println("合計は" + sum + "点です。");
System.out.println("平均は" + (double)sum / 5 + "点です。");
stdIn.close();
}
}
このプログラムでは、一人に対して1つずつ変数を割り当てています。人の数が多くなると管理が大変になってきます。
他にも問題があり、同じような作業を繰り返し行うことです。
- 点数の入力を促す。
- キーボードから読み込んだ数値を変数に格納する。
- 読み込んだ数をsumに加える。
これらをひとまとめに出来ればとても便利です。そこで、配列(array)と呼ばれるデータ構造で実現します。イメージは次の図のように考えるといいでしょう。
配列は、同一型の変数である構成要素(component)が直線状に並んだものです。個々の構成要素の型である構成要素型(component type)は、何でも構いません。
配列変数の宣言
普通の変数と同様に、配列も利用する際に宣言が必要です。以下の形式で行います。
int[] a; //int型を構成要素型とする配列の宣言①
int a[]; //int型を構成要素型とする配列の宣言②
どちらの形式でも構わないのですが、①を主に使って記述していきます。この宣言によって作られるものは、配列変数(array variable)と呼ばれる特殊な変数です。
配列本体の生成
配列の本体は、配列変数とは別に生成する必要があります。前述したプログラムでは、5人分のデータを収集したので5個の配列の本体を生成します。
new int[5]; int型を構成要素型とする構成要素が5個の配列の本体を生成
生成した配列本体と配列変数は関連付ける必要があります。関連付けは以下の代入で行えます。
a = new int[5];
これで、変数aが配列本体を参照することになります。配列変数の宣言の初期化子に、配列本体の生成式を組み込むとプログラムは簡潔になります。
int[] a = new int[5]; aは構成要素変数5の配列を参照
構成要素のアクセス
配列本体内の個々の構成要素のアクセス(読書き)は、以下に示すようにインデックス(index)を[]中に与えることによって行います。
配列変数名[インデックス]
インデックスには、「先頭の構成要素から何個後ろの構成要素であるか」を示すint型の値を与えます。
配列の構成要素
まずは、単純なプログラムを作成しましょう。構成要素型がint型である配列を作って、構成要素に値を代入して表示するプログラムです。
//IntArray1.java
//構成要素がint型の配列(構成要素は5:newによって本体を生成)
public class IntArray1 {
public static void main(String[] args){
int[] a = new int[5];
a[1] = 27;
a[2] = 55;
a[4] = a[1] * 2;
System.out.println("a[" + 0 + "] = " + a[0]);
System.out.println("a[" + 1 + "] = " + a[1]);
System.out.println("a[" + 2 + "] = " + a[2]);
System.out.println("a[" + 3 + "] = " + a[3]);
System.out.println("a[" + 4 + "] = " + a[4]);
}
}
既定値
実行結果は、値を代入していないa[0]とa[3]の値が0になっていることを示しています。配列の構成要素は、自動的に0で初期化されるという規則があります。この点は通常の変数と大きく異なります。
構成要素が初期化される値のことを既定値(default value)と呼びます。各型の既定値をまとめたのが以下の表になります。
型 | 既定値 |
byte | ゼロ すなわち(byte)0 |
short | ゼロ すなわち(short)0 |
int | ゼロ すなわち 0 |
long | ゼロ すなわち 0L |
float | ゼロ すなわち 0.0f |
double | ゼロ すなわち 0.0d |
char | 空文字 すなわち u0000 |
boolean | 偽 すなわち false |
参照型 | 空参照 すなわち null |
一般に、構成要素型がTypeである配列のことを「Type型配列」と呼びます。
要素数の取得
要素数がint型で要素数が5の配列を作って、その先頭から順に1,2,3,4,5を代入して表示するプログラムを作りましょう。
//IntArray2.java
//配列の各要素に1,2,3,4,5を代入表示
public class IntArray2 {
public static void main(String[] args){
int[] a = new int[5];
for(int i = 0; i < a.length; i++)
a[i] = i + 1;
for(int i = 0; i < a.length; i++)
System.out.println("a[" + i + "] = " + a[i]);
}
}
2つのfor文の制御式では、以下の形式が使われています。
配列変数名.length
これは、配列の要素数を取得するための式です。
配列の要素への値の読み込み
ここまでのプログラムの配列の要素数は、すべて定数でしたが、キーボードから読みこむ形に書きかえましょう。
//IntArrayScan.java
//配列の全要素に値を読み込んで表示
import java.util.Scanner;
public class IntArrayScan {
public static void main(String[] args){
Scanner stdIn = new Scanner(System.in);
System.out.print("要素数:");
int n = stdIn.nextInt();
int[] a = new int[n];
for(int i = 0; i < n; i++){
System.out.print("a[" + i + "] = ");
a[i] = stdIn.nextInt();
}
System.out.println("");
for(int i = 0; i < n; i++)
System.out.println("a[" + i + "] =" + a[i]);
stdIn.close();
}
}
プログラムの流れは以下のようになっています。
- 配列の要素数を変数nに読み込む。
- 配列の宣言。要素数がnの配列本体を生成するとともに、それを参照をするように配列変数aが初期化されます。
- for文によってiを0からn-1までインクリメントしながら、配列の要素a[i]に値を読み込みます。その結果、配列aの全要素に値が読み込まれます。
- 全要素の値を表示します。
棒グラフの表示
次は、全要素をランダムな値を埋め尽くすようにしましょう。配列の全要素に1から10の乱数を代入して表示するプログラムを以下に示します。
//IntArrayRand.java
//配列の全要素に乱数を代入して棒グラフ表示
import java.util.Random;
import java.util.Scanner;
public class IntArrayRand {
public static void main(String[] args){
Random rand = new Random();
Scanner stdIn = new Scanner(System.in);
System.out.print("要素数:");
int n = stdIn.nextInt();
int[] a = new int[n];
for(int i = 0; i < n; i++)
a[i] = 1 + rand.nextInt(10);
for(int i = 0; i < n; i++){
System.out.print("a[" + i + "] :");
for(int j = 0; j < a[i]; j++)
System.out.print('*');
System.out.println();
}
stdIn.close();
}
}
最初のfor文では、配列aの全要素に乱数を代入しています。2つ目のfor文では、記号文字*を並べた棒グラフによって要素の値を表示します。そのために、変数iの値を0からn-1までインクリメントしながら、以下の処理をn回繰り返します。
- このfor文の繰り返し回数はa[i]で、この数だけ*を表示します。
- 改行
配列の初期化と代入
配列の全要素は既定値である0で初期化されます。もし、個々の要素に入れるべき値があらかじめ分かっているのであれば、明示的に初期化を行うべきです。配列本体の個々の要素を初期化するようなプログラムを作りましょう。
//IntArrayInit.java
//配列の各要素を数字で初期化表示
public class IntArrayInit {
public static void main(String[] args){
int[] a = {1,2,3,4,5};
for(int i = 0; i < a.length; i++)
System.out.println("a[" + i + "] = " + a[i]);
}
}
配列に与える初期化子は、各要素に対する初期化しをコンマで区切って順に並べてそれを{}で囲んだものです。生成される配列の要素数は、初期化子の個数に基づいて自動的に決定されます。
配列による成績処理
成績処理のプログラムを配列を用いて作り直しましょう。そのプログラムが以下になります。
//PointSumAveArray.java
//点数を読み込んで合計点、平均点を表示
import java.util.Scanner;
public class PointSumAveArray {
public static void main(String[] args){
Scanner stdIn = new Scanner(System.in);
int sum = 0;
final int num = 5;
int[] score = new int[num];
System.out.println(num + "人分の点数を入力してください。");
for(int i = 0; i < num; i++){
System.out.print((i + 1) + "番の点数:");
score[i] = stdIn.nextInt();
sum += score[i];
}
System.out.println("合計は" + sum + "点です。");
System.out.println("平均は" + (double)sum / num + "点です。");
stdIn.close();
}
}
- 学生の人数を整数リテラルではなく、final変数で表しています。
- 配列のインデックスは0から始まる値です。このプログラムでは、点数の入力をする際に、インデックスに1を加えた「*番目の点数」と表示しています。