本章では配列について、学習します。
本章で学習する内容を動画としてまとめたものです。最初に一通り見終わった後で、学習に入るようにしてください。
配列を使うと、同じようなデータをいくつか扱うときに、まとめて扱うことができます。
同じようなデータを複数扱う場合、同じ型の変数をいくつも用意すると変数が多くなり、変数の扱いが煩雑になってきます。
そんなときに、その複数のデータをまとめて格納する配列を使うと、プログラムがすっきりとします。
配列は、以下の図のようなイメージです。
それでは、配列の宣言と生成について、学習しましょう。まずは、配列の宣言からです。
配列の宣言は、以下の書式となります。基本データ型と参照型のどちらの場合でも、同じ構文となります。
データ型[] 配列変数名;
プログラムで書くと以下のようになります。int型の配列とString型の配列の両方を宣言しています。
int[] tokuten; // int型の配列 tokutenの宣言
String[] name; // String型の配列 nameの宣言
型の宣言で記述されている「[]」は、その変数が配列であることを示しています。
これで、複数の変数をまとめて扱える配列の宣言ができました。
次に配列の生成を行います。配列の生成とは、実際にデータを格納するためのメモリー領域を確保することです。
配列の生成は、「new」という演算子を使います。
中身の値を指定せずに、配列の大きさだけ指定するには、以下の書式となります。
配列変数名 = new データ型[配列の大きさ];
プログラムで書くと以下のようになります。
5つの領域を持ったint型の配列tokutenと3つの領域を持ったString型の配列nameを生成しています。
tokuten = new int[5]; // int型の配列 tokutenの生成
name = new String[3]; // String型の配列 nameの生成
以下のように宣言と生成を同時に行うこともできます。
int[] tokuten = new int[5];
String[] name = new String[3];
生成した配列は、「添え字(そえじ)」を使って管理されます。
添え字は0から始まり、 大きさがnの配列では0から(n-1)が添字の番号になります。
配列の各領域は、要素と呼びます。配列の各要素は、添え字を使って以下のように表現します。
配列変数名[添え字]
プログラムで書くと以下のようになります。
tokuten[0]; // int型の配列 tokutenの1番目の要素
tokuten[2]; // int型の配列 tokutenの3番目の要素
name[0]; // String型の配列 nameの1番目の要素
参照型の配列の場合、宣言と生成をしただけでは、各要素の初期値は、「null(ヌル)」という何も値がないという意味の特殊な値になります。
プリミティブ型の配列の場合、各型によって、自動的に初期値が設定されます。int型の場合は「0」が設定されます。
配列の宣言と生成を行った後は、適切な値を代入する必要があります。
配列への代入では、添え字が使用されます。代入する値は、配列のデータ型と同じデータ型でなければいけませんので、注意してください。
以下がサンプルソースです。各要素に添え字を使って、それぞれ10、20、30、40、50を代入しています。
int[] tokuten = new int[5];
tokuten[0] = 10;
tokuten[1] = 20;
tokuten[2] = 30;
tokuten[3] = 40;
tokuten[4] = 50;
また、以下のように配列の宣言と生成を行うと同時に、値を代入することもできます。
代入する値の個数が、その配列の要素の数となります。
以下がサンプルソースです。配列を宣言・生成する構文の後ろに「{}」を記述し、その中に配列へ代入したい値を「,(カンマ)」で区切って書きます。
int[] tokuten = new int[]{10,20,30,40,50};
newの記述を省略する事も可能です。
int[] tokuten = {10,20,30,40,50};
また、繰り返しfor文を使用して配列の中に値を代入することもできます。以下がサンプルソースです。
String[] array = new String[5]; // 要素の初期値は null
for (int i = 0; i < 5; i++) {
// 配列の各要素を文字列 A0、A1、A2、A3、A4を持つ
// String型のインスタンスで初期化します。
array[i] = new String("A" + i);
}
それでは、配列に代入した値を取得する方法を学習しましょう。
配列の要素の値を取得する場合は、以下のように添え字で番号を指定します。
System.out.println(tokuten[2]); // 配列tokutenの3番目の要素の値をコンソールに出力します
複数の要素の値を取得する場合には、for文を用いて以下のように記述します。
for (int i = 0; i < 5; i++) {
// 配列tokutenの1番目の要素の値から順番にコンソールに出力します
System.out.println(tokuten[i]);
}
配列は、lengthフィールドというフィールドを使って、配列の長さ(要素の数)を取得することができます。
配列の全ての要素を取得する場合に、繰り返し処理と組み合わせて使用することが多いです。
lengthフィールドの書式は、以下のとおりです。以下がサンプルソースです。
// 配列の宣言と生成
String[] array = new String[5];
// 配列への代入
for (int i = 0; i < array.length; i++) {
// 配列の各要素を文字列 A0、A1、A2、A3、A4を持つ String 型のインスタンスで初期化します。
array[i] = new String("A" + i);
}
// 配列から値を取得
for (int i = 0; i < array.length; i++) {
// 配列arrayの1番目の要素の値から順番にコンソールに出力します
System.out.println(array[i]);
}
// 配列の要素数をコンソールに出力
System.out.println("配列arrayの要素の数は、" + array.length + "です。");
拡張for文とはJDK5から追加されたfor文の構文で、書式は以下になります。
for (変数の型 変数名 : 配列名) {
繰り返したい処理
}
繰り返したい処理を{}の中に書くことは、これまでと変わりありません。
繰り返し処理は、配列の要素数分行われます。
拡張for文を使用した配列の各要素へのアクセス方法は以下になります。
int[] tokuten = {10, 20, 30, 40, 50};
for (int tensu : tokuten) {
System.out.println(tensu);
}
このように繰り返し処理の中で各要素の値が格納された状態の変数を使用することが可能です。
ただし、拡張for文は、配列などのように複数の要素を持ち繰り返しの対象となるものが存在しなければ、使用することはできません。
そのため、配列が存在しない状態で、「拡張for文を用いて10回の繰り返し処理を行う」といったことはできませんので、通常のfor文を使用する必要があります。
通常のfor文と拡張for文を用いた繰り返し処理の異なる点として、拡張for文は単純な変数名を使用して値を取得していたことに対し、通常のfor文は配列の添え字を使用して各要素へのアクセスを行っています。
書き方は異なりますが、拡張for文を使う利点としては、要素の数をプログラムに直接書かなくて良いので、「java.lang.ArrayIndexOutOfBoundsException」の例外(エラー)が発生しなくなることです。
配列内の各要素へアクセスする(各要素を取得する)場合、基本的には拡張for文を使用していくことになるでしょう。しかし、場合によっては通常のfor文を使用する方が妥当であることもあります。
その状況によって適切なプログラミングを行いましょう。
次は、少し応用的な配列の使い方を学習します。
配列の各要素に、配列を代入することができます。
このような、入れ子構造の配列データのことを、多次元配列と言います。
今回は2次元配列について説明します。
2次元配列は、配列の各要素にまた別の配列が代入されている配列です。
この2次元配列によって、更にまとまったデータを扱うことができるようになります。
以下が2次元配列の宣言の書式です。
データ型[][] 配列変数名;
以下がサンプルソースとなります。
int[][] array;
ちなみに、3次元配列の宣言は以下のようになります。
int[][][] array;
2次元配列の生成は、以下のようになります。
int[][] array = new int[3][2];
「new int」の後の最初の[3]は、1次元目の配列の要素数を、次の[2]は、2次元目の配列の要素を定義しています。
代入は以下のように行います。
array[0][0] = 10;
array[0][1] = 20;
array[1][0] = 30;
array[1][1] = 40;
array[2][0] = 50;
array[2][1] = 60;
宣言と同時に値を代入する場合は、以下のようにします。
int[][] array = { {10,20},{30,40},{50,60} };
以下のように、不規則な配列を作成することも可能です。
配列の中の各要素が配列となっていますが、2次元目の各配列の要素の数が異なっています。
int[][] array = { // 以下の 3 つの配列を持つ配列
{82}, // 1 つの要素をもつ配列
{76,56,67,58}, // 4 つの要素をもつ配列
{50,48} // 2 つの要素をもつ配列
};
mainメソッドの()の中にString型の配列argsが定義されているのを気づいていたでしょうか。
public static void main(String[] args) { // mainメソッド
}
この配列argsを使うと、プログラムを実行するときに、mainメソッドに値を引き渡すことができます。
プログラムを実行するときに、値やファイル名をメインメソッドへ引き渡すことによって、プログラムの動作をif文で分岐させたり、ファイルのデータを読み込んだりすることが可能になります。
このような、プログラム実行時にメインメソッドに引き渡す値のことを、コマンドライン引数(ひきすう)と言います。
Eclipseでは、argsに値を引き渡すときの記述は、以下のとおりとなります。
クラスを新たに作成し、以下のサンプルソースをそのまま書き写してください。
public class ArgsTest1 {
public static void main(String[] args) {
for (String str : args) {
System.out.println(str);
}
}
}
上記のクラスを右クリックし、「実行」 ⇒ 「実行の構成」を選択します。
「実行構成」画面が表示されますので、「引数」タブをクリックして、「プログラムの引数」にコマンドライン引数を入力します。
なお、「名前」に表示されているクラス名が異なっている場合、左側のフィルターから、今回作成したクラスを選択するようにしてください。
このクラスに「A B C D(文字の間は半角スペース)」を引数として引渡し、実行してみます。
コマンドライン引数は、配列となっていますので、複数の値をプログラム実行時にプログラムに引き渡すことができるようになっています。
以下のように出力されたでしょうか。2つ以上の引数を引き渡す場合、引数の間に半角スペースを空ける必要があります。
この例では、コマンドライン引数をコンソールに表示しているだけですが、この引数を処理の中で活用することも可能です。
A
B
C
D
以下のサンプルソースでは、引き渡した値で処理を分岐させています。
引渡したコマンドライン引数の個数によって、コンソールに出力するメッセージを制御しています。
サンプルのように、処理を分岐させるためにコマンドライン引数を使うこともできます。
public class ArgsTest2 {
public static void main(String[] args) {
// コマンドライン引数が1つの場合
if (args.length == 1) {
System.out.println("コマンドライン引数が1つ引き渡されました。");
// コマンドライン引数が2つ以上の場合
} else if (args.length >= 2) {
System.out.println("コマンドライン引数が2つ以上引き渡されました。");
}
}
}
コマンドライン引数の使用頻度は高くはありませんが、プログラム実行時にプログラムへ何か値を引き渡して実行したい場合に使用することができるものですので、覚えておくと便利でしょう。
以下のプログラムでは、配列変数seisekiが宣言されており、要素として点数が格納されています。
これらの点数の合計点と平均点を計算し、計算結果が画面に表示されるように、必要な記述を追記して、プログラムを完成させてください。
添え字を使用して、配列の各要素を取得し、合計点と平均点を計算してください。
public class ArrayMondai6_1 {
public static void main(String[] args) {
// 点数の配列
int[] seiseki = new int[]{65, 80, 75, 100, 40};
int goukei = 0; // 合計点
int heikin = 0; // 平均点
for (int i = 0; i < seiseki.length; i++) {
// 合計点の計算
/* ここに追加 */
}
// 平均点の計算
/* ここに追加 */
// 合計点、平均点の表示
System.out.println("合計点は、" + goukei + "です。");
System.out.println("平均点は、" + heikin + "です。");
}
}
public class ArrayMondai6_1 {
public static void main(String[] args) {
// 点数の配列
int[] seiseki = new int[]{65, 80, 75, 100, 40};
int goukei = 0; // 合計点
int heikin = 0; // 平均点
for (int i = 0; i < seiseki.length; i++) {
// 合計点の計算
goukei += seiseki[i];
}
// 平均点の計算
heikin = goukei / seiseki.length;
// 合計点、平均点の表示
System.out.println("合計点は、" + goukei + "です。");
System.out.println("平均点は、" + heikin + "です。");
}
}
for文の繰り返しの中で、配列seisekiの各要素を、「seiseki[i]」のように添え字用の変数iを使用して順番に取得し、それを変数goukeiに加算していきます。
for文を使用して、配列seisekiのi番目の要素(seiseki[i])を一つずつ変数goukeiに加算しています。
合計点を計算後、lengthフィールドを使用して取得した配列の要素の数で合計点を割って、平均点を計算しましょう。
以下のプログラムでは、配列変数seisekiが宣言されており、要素として点数が格納されています。
それらの点数の中から最高点を取得し、画面に表示されるように、必要な記述を追記して、プログラムを完成させてください。
添え字を使用して、配列の各要素を取得し、その中から最高点を取得してください。
public class ArrayMondai7_1 {
public static void main(String[] args) {
// 点数の配列
int[] seiseki = new int[]{65, 80, 75, 100, 40};
// 最高点
int maxTensu;
// 初期値
maxTensu = seiseki[0];
for (int i = 0; i < seiseki.length; i++) {
// 最高点の取得
/* ここに追加 */
}
// 最高点の表示
System.out.println("最高点は、" + maxTensu + "です。");
}
}
public class ArrayMondai7_1 {
public static void main(String[] args) {
// 点数の配列
int[] seiseki = new int[]{65, 80, 75, 100, 40};
// 最高点
int maxTensu;
// 初期値
maxTensu = seiseki[0];
for (int i = 0; i < seiseki.length; i++) {
// 最高点の取得
if (maxTensu < seiseki[i]) {
// 変数maxTensuを要素の値に変更
maxTensu = seiseki[i];
}
}
// 最高点の表示
System.out.println("最高点は、" + maxTensu + "です。");
}
}
配列seisekiから最高点を取得するために、変数maxTensuに配列の最初の要素を代入しておきます。
繰り返し処理の中で配列の各要素を順番に取得し、変数maxTensuと取得した値の大きさを比較します。
maxTensuよりも配列の各要素の値が大きい場合、maxTensuをその値に変更しています。
それを繰り返すと、最終的に配列の中で一番大きい値がmaxTensuに残ります。
問題1を拡張for文を利用して書き換えてください。
public class ArrayMondai7_2 {
public static void main(String[] args) {
// 点数の配列
int[] seiseki = new int[]{65, 80, 75, 100, 40};
// 最高点
int maxTensu;
// 初期値
maxTensu = seiseki[0];
// 拡張for文を利用した最高点の取得
/* ここに追加 */
// 最高点の表示
System.out.println("最高点は、" + maxTensu + "です。");
}
}
※この問題の解答は掲載しておりません。Tech Fun ITスクールのJava研修では、講師が丁寧に解説しています。
2次元配列の練習問題です。
以下のプログラムでは、2次元配列seisekiが宣言されており、要素として点数が格納されています。
これらの点数の合計を計算し、画面に表示されるように、必要な記述を追記して、プログラムを完成させてください。
public class ArrayMondai8_1 {
public static void main(String[] args) {
// 2次元配列seisekiの宣言と要素の代入
int[][] seiseki = { {65, 80, 75}, // 山田さんの国語、数学、英語の点数
{100, 90, 90}, // 佐藤さんの国語、数学、英語の点数
{40, 30, 0} }; // 鈴木さんの国語、数学、英語の点数
// 山田さん、佐藤さん、鈴木さんのそれぞれの合計点を計算
/* ここに追加 */
// 山田さん、 佐藤さん、鈴木さんのそれぞれの合計点を表示
/* ここに追加 */
}
}
※この問題の解答は掲載しておりません。Tech Fun ITスクールのJava研修では、講師が丁寧に解説しています。
コマンドライン引数の練習問題です。
「コマンドライン引数」に「65 80 75 100 40」と点数を入力します。
「コマンドライン引数」に入力された値を、文字列型配列に逆順(「40 100 75 80 65」の順番)に格納し、その配列から拡張for文を使って要素を取り出し、 コンソールに出力してください。
public class ArrayMondai9_1 {
public static void main(String[] args) {
// 逆順の点数を格納する配列を宣言
String[] score = new String[args.length];
// コマンドライン引数の配列argsに格納されている点数を逆順にscoreに格納
for (int i = args.length - 1; 0 <= i; i--) {
score[args.length - i - 1] = args[i];
}
// 逆順に格納した配列の中身を出力
for (String str : score) {
System.out.println(str);
}
}
}
コマンドライン引数に入力した値は、mainメソッドの引数「String[] args」に引き渡されます。
for文を使用して配列argsの各要素を逆順に取得します。ここで、args.lengthに-1をすることに注意してください。
また、配列scoreの要素番号は、0から1ずつ加算していく必要があるため、「args.length – i – 1」となります。
疑問点や不明点がある場合は、講師に質問して早めに解消しておきましょう。
配列についての説明は、以上です。