[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

情報処理技法(Javaプログラミング)I 第8回

目次
索引

配列(1)

配列とは

変数を用いるとデータを一つ格納できることは、すでに学びました。 たくさんのデータを格納するには、データの個数だけ変数を用意すれば可能です。 しかし、それらのデータを系統的に取り扱うことは困難です。

配列 array )というものを用いると、たくさんのデータを系統的に格納することができます。 配列とは、データの「入れ物」が並んだものと考えてください。 次の図は、配列のイメージです。

配列のイメージ
配列のイメージ

「入れ物」の一つ一つを 配列要素 array element )とよびます。 配列には次のような特徴があります。

配列の使い方

変数を使うためには、変数の宣言が必要でした。 int x; のように変数を宣言すると、変数 x に整数(int型)が一つ格納できました。

配列を使うためには、配列の宣言と配列の生成という二段階の手続きが必要です。 次のプログラムは、配列を宣言し、生成し、その3番目に整数23を格納し、それを出力するものです。

ArrayTest.java
/*  1*/ class ArrayTest { // 配列のテスト
/*  2*/     public static void main (String[] args) {
/*  3*/         int[] a; // 宣言
/*  4*/         a = new int[10]; // 10個生成
/*  5*/         a[3] = 23; // 3番目に格納
/*  6*/         System.out.println(a[3]); // 3番目を出力
/*  7*/     }
/*  8*/ }
コンソール
23

Completed with exit code: 0

整数(int型)の配列の場合、配列の宣言は次のように書きます。

int[] 配列名;

ここで、「 配列名 」は配列の名前です。 配列の生成は、

配列名 = new int[要素数];

と書きます。 ここで、「 要素数 」は配列の要素数です。

上記のプログラムでは、3行目で名前が a である配列を宣言しています。 また、4行目で要素数が10である配列を生成しています。

配列要素にデータを格納するには、

配列名[番号] = ;

と書きます。 「 配列名 」の「 番号 」番目の要素に「 」の値を格納します。 ここで、「 番号 」は数そのものである必要はありません。 数を値に持つならば、変数や式でもかまいません。 例えば、変数 i の値が3で x の値が100ならば、

b[i - 1] = x + 1;

によって配列 b の2番目の要素に101が格納されます。 式

配列名[番号]

で、「 配列名 」の「 番号 」番目の要素が取り出せます。 なお、配列の何番目の要素かを表すこの「 番号 」を、配列の 添字 (そえじ)( subscript )、または インデックス index )とよびます。

上記のプログラムでは、5行目で配列の3番目の要素にデータ23を格納しています。 また、6行目ではそのデータを取り出して出力しています。

上記のプログラムにおいて、 a [10] は存在しないことに注意してください。 このような、存在しない要素にデータを格納しようとしたり、データを取り出そうとすると、エラーが発生します。

ArrayError.java
/*  1*/ class ArrayError { // 配列のエラー
/*  2*/     public static void main (String[] args) {
/*  3*/         int[] a;
/*  4*/         a = new int[10]; // 0番目から9番目まで
/*  5*/         a[10] = 100; // 10番目は存在しない
/*  6*/         System.out.println(100);
/*  7*/     }
/*  8*/ }
コンソール
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
        at ArrayError.main(ArrayError.java:5)

Completed with exit code: 1

なお、配列の要素数をどこかに記録しておく必要はありません。 これは、式

配列名.length

によっていつでも取り出せます。

注意: 教科書によっては、配列の宣言は

int a[];

などと書くと説明しています。 Javaでは、 int[] a; int a[]; は同じ意味です。 ただし、これらを混在させるのは混乱のもとですので、この授業では前者に統一します。

配列の初期化

上記のイメージの通り、配列にデータを格納しましょう。 これは、配列の宣言、配列の生成、配列要素への代入という手順を踏むとできます。 以下はそのようなプログラム(部分)です。

int[] a;
a = new int[10];
a[0] = 20; a[1] = 21; a[2] = 22; a[3] = 23; a[4] = 24;
a[5] = 25; a[6] = 26; a[7] = 27; a[8] = 28; a[9] = 29;

次のように書くと、配列の宣言と生成が同時に行えます。

int[] a = new int[10]; // 宣言と生成
a[0] = 20; a[1] = 21; a[2] = 22; a[3] = 23; a[4] = 24;
a[5] = 25; a[6] = 26; a[7] = 27; a[8] = 28; a[9] = 29;

さらに、データの格納も同時に行うことができます。 これは次のように書きます。

int[] a = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29};

このことを、配列の 初期化 initialization )とよびます。 配列の初期化では、キーワード new や配列の要素数は書きません。

配列と繰返し

配列のプログラムでは、繰返しを利用するのが普通です。 つまり、ループ変数 i を用意し、for文などの繰返しの中で、配列要素 a [ i ]からデータを取り出したり、 a [ i ]にデータを格納したりします。

次のプログラムは、配列 a の要素をすべて出力するものです。

ArrayPrint.java
/*  1*/ class ArrayPrint { // 配列の出力
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         int[] a = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29}; // 初期化
/*  5*/         for (i = 0; i < a.length; i++) { // aの要素数回繰り返す
/*  6*/             System.out.println("a[" + i + "] = " + a[i]);
/*  7*/         }
/*  8*/     }
/*  9*/ }
コンソール
a[0] = 20
a[1] = 21
a[2] = 22
a[3] = 23
a[4] = 24
a[5] = 25
a[6] = 26
a[7] = 27
a[8] = 28
a[9] = 29

Completed with exit code: 0

4行目で配列 a を初期化します。 式 a . length の値は10なので、5行目のfor文では変数 i は0から9まで動きます。 6行目で配列要素 a [ i ]の値を詳しく出力します。

配列の使用例

配列の使用例として、はじめに、配列要素の総和を求めます。

{100, 200, 100, 300, 200}

で表される配列の要素の合計を、レジの計算の要領で算出します。 つまり、

sum += a[0]; // i = 0
sum += a[1]; // i = 1
sum += a[2]; // i = 2
...

のように計算します。 プログラムは次の通りです。

ArraySummation.java
/*  1*/ class ArraySummation { // 配列の総和
/*  2*/     public static void main (String[] args) {
/*  3*/         int i, sum = 0;
/*  4*/         int[] a = {100, 200, 100, 300, 200};
/*  5*/         for (i = 0; i < a.length; i++) {
/*  6*/             sum += a[i];
/*  7*/         }
/*  8*/         System.out.println("合計は" + sum);
/*  9*/     }
/* 10*/ }
コンソール
合計は900

Completed with exit code: 0

次の例は、配列要素の最大値を求めるものです。

{100, 200, 100, 300, 200}

で表される配列の要素の最大値は、人間が見れば 300 だと分かります。

この問題をコンピュータで解決するのに、勝ち抜き方式を使うことにします。 これは、はじめに最初の要素をとりあえずチャンピオンにします。 続いて、次の要素とチャンピオンが勝負をし、チャンピオンが負けたら勝者を新たにチャンピオンにします。 これを要素がなくなるまで繰り返します。 最後のチャンピオンが全体のチャンピオンであるというわけです。

具体的には、

max = a[0];
if (a[1] > max) { // i = 1
    max = a[1];
}
if (a[2] > max) { // i = 2
    max = a[2];
}
...

のようにして、最大値を求めます。 プログラムは次の通りです。

ArrayMaximum.java
/*  1*/ class ArrayMaximum { // 配列の最大値
/*  2*/     public static void main (String[] args) {
/*  3*/         int i, max;
/*  4*/         int[] a = {100, 200, 100, 300, 200};
/*  5*/         max = a[0]; // とりあえずチャンピオンにする
/*  6*/         for (i = 1; i < a.length; i++) {
/*  7*/             if (a[i] > max) { // チャンピオンが負けたら
/*  8*/                 max = a[i]; // 勝者をチャンピオンにする
/*  9*/             }
/* 10*/         }
/* 11*/         System.out.println("最大値は" + max);
/* 12*/     }
/* 13*/ }
コンソール
最大値は300

Completed with exit code: 0

最後の例として、アンケートの集計を行います。 ある議題に関するアンケート調査を25人に対して行い、次のような回答(1=賛成、2=反対)が得られたとします。

2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 1, 1

この回答から、賛成が何人、反対が何人かを求めるプログラムを考えます。

まず、回答を格納する配列 answers を用意します。 配列の初期化を使って、これに回答を格納します。 そして、この配列から回答をひとつずつ取り出し、回答で場合分けをし、その人数を1増加させるという操作を繰り返して、回答ごとに人数を数えます。

YesNoQuestion.java
/*  1*/ class YesNoQuestion { // 賛成反対アンケート
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         int yesCount = 0, noCount = 0; // 賛成の人数と反対の人数
/*  5*/         int[] answers = {
/*  6*/             2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 
/*  7*/             1, 2, 1, 1, 2, 1, 2, 2, 1, 2,
/*  8*/             1, 2, 1, 1, 1
/*  9*/         };
/* 10*/         for (i = 0; i < answers.length; i++) {
/* 11*/             switch (answers[i]) { // 回答で場合分け
/* 12*/                 case 1: yesCount++; break; // 賛成の場合
/* 13*/                 case 2: noCount++; break; // 反対の場合
/* 14*/                 default: System.out.println("エラー"); break;
/* 15*/             }
/* 16*/         }
/* 17*/         System.out.println("賛成" + yesCount + "人");
/* 18*/         System.out.println("反対" + noCount + "人");
/* 19*/     }
/* 20*/ }
コンソール
賛成16人
反対9人

Completed with exit code: 0

演習8

ある会社のある課には社員が25人います。 社員の血液型を調べることになりました。 調査結果(1=A型、2=B型、3=O型、4=AB型)は次の通りです。

1, 3, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 2, 4, 2, 1, 1, 1, 1, 1, 2, 4, 3

このデータをプログラムの中に書き、配列の初期化の要領で配列に格納してください。 そして、それぞれの血液型の人数を数えて出力するプログラムを作成してください。

BloodTypes.java
class BloodTypes {
    public static void main (String[] args) {
        int[] answers = {
            1, 3, 1, 2, 2, 2, 1, 1, 2, 2,
            2, 2, 2, 1, 2, 4, 2, 1, 1, 1,
            1, 1, 2, 4, 3
        };



    }
}
コンソール
A型10人
B型11人
O型2人
AB型2人

Completed with exit code: 0

余力のある人は、割合を計算して出力してください。

ヒント: 割合を計算するとき、人数が整数なので、そのまま割り算をすると0になってしまいます。 人数を表す変数の左側に (double) と書き、人数を実数に変換してから割り算をすると、実数で割合が計算できます。

コンソール
A型10人(40.0%)
B型11人(44.0%)
O型2人(8.0%)
AB型2人(8.0%)

Completed with exit code: 0

レポート課題

今日の演習8の答案(Javaプログラム)をメールで提出してください。 差出人は大学発行のメール・アドレス(学生番号@cis.twcu.ac.jp)とし、宛先はkonishi@cis.twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(11月19日)を明記してください。


参考文献


[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

2021年11月19日更新
小西 善二郎 <konishi@cis.twcu.ac.jp>
Copyright (C) 2021 Zenjiro Konishi. All rights reserved.