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

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

目次
索引

ラッパー・クラス

以前、Javaのデータ型は、基本データ型と参照データ型の大きく2つに分類される、と説明しました。 基本データ型には、整数型、実数型、論理型、文字型の4種類があり、整数型や実数型にも、いくつか種類がありました。

Javaでは、それぞれの基本データ型に対して、参照データ型が用意されています。 そのような参照データ型を、 ラッパー・クラス wrapper class )とよびます。

基本データ型とラッパー・クラスの対応は以下の通りです。 基本的に、基本データ型の先頭を大文字にするとラッパー・クラスになりますが、intとcharは違います。

基本データ型とラッパー・クラス
種類 基本データ型 ラッパー・クラス
整数型 byte Byte
整数型 short Short
整数型 int Integer
整数型 long Long
実数型 float Float
実数型 double Double
論理型 boolean Boolean
文字型 char Character

以下で説明する、リストやハッシュを利用するときは、基本データ型が使えず、参照データ型を使うことになっています。 なので、リストやハッシュで基本データ型を使いたかったら、代わりにラッパー・クラスを使うのです。 リストやハッシュのプログラムでは、 int double の代わりに、 Integer Double と書くということです。


リスト

リストとは

以前、配列を説明したときに、配列は一度生成すると要素数は変えられない、と言いました。 どうしても要素数を変えたければ、大きめの配列の先頭部分を利用する、より大きな配列にコピーする、といった工夫が必要でした。 アレイ・リストというものを使うと、これらの工夫を自動的にやってくれます。

アレイ・リスト array list )とは、配列のようにデータを一列に格納でき、かつデータの追加や削除ができるデータ構造です。 ここでは、アレイ・リストを短く リスト list )とよびます。

リストの要素を リスト要素 list element )とよびます。 1つのリストの中で、リスト要素のデータ型はすべて同じ(これは配列も一緒)で、さらに、参照データ型でなくてはなりません。

まとめると、以下のようになります。

配列とリストの比較

配列 リスト
要素数 変えられない 変えられる
要素のデータ型 なんでもよい 参照データ型のみ

リストの使い方

以下はリストのプログラムの例です。

ListTest.java
/*  1*/ import java.util.*;
/*  2*/ 
/*  3*/ class ListTest { // リストのテスト
/*  4*/     public static void main (String[] args) {
/*  5*/         ArrayList<Integer> list = new ArrayList<Integer>(); // 宣言と生成
/*  6*/         list.add(10); // 追加
/*  7*/         list.add(11); // 追加
/*  8*/         list.add(12); // 追加
/*  9*/         list.add(13); // 追加
/* 10*/         list.add(14); // 追加
/* 11*/         System.out.println(list); // すべて出力
/* 12*/     }
/* 13*/ }
コンソール
[10, 11, 12, 13, 14]

Completed with exit code: 0

プログラムでリストを扱うときは、先頭に

import java.util.*;

と書きます。

整数(int型)のリストのための変数を宣言するには、 int Integer に置き換え、

ArrayList<Integer> リスト名;

と書きます。 整数(int型)のリストを生成して変数に代入するには、 int Integer に置き換え、

リスト名 = new ArrayList<Integer>();

と書きます。 配列と違い、要素数は書きません。

なお、宣言と生成は、

ArrayList<Integer> リスト名 = new ArrayList<Integer>();

とまとめられます。

実数(double型)のリストの場合は、 double Double に置き換え、

ArrayList<Double> リスト名 = new ArrayList<Double>();

となります。

文字列のリストの場合は、文字列は参照データ型なので、 String のまま

ArrayList<String> リスト名 = new ArrayList<String>();

です。

要素数を書かないということは、リストは最初、要素数0です。 要素数が0のリストを 空リスト empty list )とよびます。

リストに要素を追加するには、

リスト名.add();

と書きます。 これで、「リスト名」の最後に「値」が追加されます。 これを繰り返せば、複数の要素があるリストになります。

リストのすべての要素を確認するには、

System.out.println(リスト名);

と書きます。 これで、四角括弧に囲まれた要素の並びが出力されます。

リストに要素があれば、リスト要素に値を代入したり、リスト要素から値を取得したりできます。 ただし、プログラムの書き方は、配列と全然違います。

ListSetGet.java
/*  1*/ import java.util.*;
/*  2*/ 
/*  3*/ class ListSetGet { // リストに対する代入と取得
/*  4*/     public static void main (String[] args) {
/*  5*/         ArrayList<Integer> list = new ArrayList<Integer>();
/*  6*/         list.add(100); // 追加
/*  7*/         list.add(101); // 追加
/*  8*/         list.set(1, 200); // 1番目に200を代入
/*  9*/         System.out.println(list.get(0)); // 0番目を取得
/* 10*/         System.out.println(list.get(1)); // 1番目を取得
/* 11*/     }
/* 12*/ }
コンソール
100
200

Completed with exit code: 0

「リスト名」の「添字」番目に「値」を代入するには、

リスト名.set(添字, );

と書きます。 「リスト名」の「添字」番目の値を取得するには、

リスト名.get(添字)

と書きます。

リストの要素数は、

リスト名.size()

で分かります。

以上をまとめ、配列と比較すると、以下のようになります。

配列とリストの使い方の比較

配列 リスト
値の追加 (不可能) リスト名 .add( );
値の代入 配列名 [ 添字 ] = ; リスト名 .set( 添字 , );
値の取得 配列名 [ 添字 ] リスト名 .get( 添字 )
要素数 配列名 .length リスト名 .size()

リストは生成された段階では空リストですが、必ずしも一行一行要素を追加するわけではありません。 例えば、要素数10のリストが必要であれば、for文で要素の追加を10回繰り返せばよいのです。

リストのすべての要素にアクセスするときも、for文を使います。 このとき、繰り返す回数は、リストの要素数である、リスト名 .size() とします。

ListLoop.java
/*  1*/ import java.util.*;
/*  2*/ 
/*  3*/ class ListLoop { // リストのループ
/*  4*/     public static void main (String[] args) {
/*  5*/         int i;
/*  6*/         ArrayList<Integer> list = new ArrayList<Integer>();
/*  7*/         for (i = 0; i < 10; i++) { // 10回繰り返す
/*  8*/             list.add(0); // 最後に0を追加
/*  9*/         }
/* 10*/         for (i = 0; i < list.size(); i++) { // リストの要素数回繰り返す
/* 11*/             System.out.println(list.get(i));
/* 12*/         }
/* 13*/     }
/* 14*/ }
コンソール
0
0
0
0
0
0
0
0
0
0

Completed with exit code: 0

リストの初期化

配列のときは、初期化ということを行うと、配列要素に一気に代入することができました。 リストでも、以下のようにすると初期化ができます。

ArrayList<Integer> リスト名 = new ArrayList<Integer>(Arrays.asList(値の並び));

つまり、リストの宣言・生成の括弧の中に Arrays.asList() を書き、その括弧の中に代入したい値をコンマで区切って並べるのです。

以下のプログラムでは、初期化を利用して要素数10のリストを生成しています。 行が長くなるので、値の並びで改行しています。

ListInitialize.java
/*  1*/ import java.util.*;
/*  2*/ 
/*  3*/ class ListInitialize { // リストの初期化
/*  4*/     public static void main (String[] args) {
/*  5*/         ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(
/*  6*/             20, 21, 22, 23, 24, 25, 26, 27, 28, 29
/*  7*/         )); // リストの初期化
/*  8*/         System.out.println(list);
/*  9*/     }
/* 10*/ }
コンソール
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]

Completed with exit code: 0

リスト要素の追加と削除

配列とリストの一番の違いは、リストは要素の追加や削除ができることです。 今までは、リストに要素を追加するとき、リスト名 .add( ); としました。 これはリストの最後に「値」を追加するものです。 リストの「添字」番目に「値」を追加するには、

リスト名.add(添字, );

とします。

ListAdd.java
/*  1*/ import java.util.*;
/*  2*/ 
/*  3*/ class ListAdd { // リストの要素の追加
/*  4*/     public static void main (String[] args) {
/*  5*/         ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(
/*  6*/             10, 11, 12, 13, 14
/*  7*/         ));
/*  8*/         list.add(1, 20); // 1番目に20を追加
/*  9*/         System.out.println(list);
/* 10*/     }
/* 11*/ }
コンソール
[10, 20, 11, 12, 13, 14]

Completed with exit code: 0

リストの「添字」番目を削除するには、

リスト名.remove(添字);

とします。

ListRemove.java
/*  1*/ import java.util.*;
/*  2*/ 
/*  3*/ class ListRemove { // リストの要素の削除
/*  4*/     public static void main (String[] args) {
/*  5*/         ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(
/*  6*/             10, 11, 12, 13, 14
/*  7*/         ));
/*  8*/         list.remove(1); // 1番目を削除
/*  9*/         System.out.println(list);
/* 10*/     }
/* 11*/ }
コンソール
[10, 12, 13, 14]

Completed with exit code: 0

ハッシュ

ハッシュとは

配列やリストは、要素を一列に並べたものですが、「添字と値の対応」と考えることもできます。 例えば、配列の初期化

int[] a = {10, 11, 12, 13, 14};

は、

int[] a;
a[0] = 10; // 添字0と値10の対応
a[1] = 11; // 添字1と値11の対応
a[2] = 12; // 添字2と値12の対応
a[3] = 13; // 添字3と値13の対応
a[4] = 14; // 添字4と値14の対応

と同じですが、これを、添字0と値10の対応、添字1と値11の対応、…と考えるのです。

ハッシュ・マップ hash map )とは、配列やリストにおける「添字と値の対応」を、「キーと値の対応」に置き換えたデータ構造です。 ここでキーは、整数でも文字列でもよいです。

ハッシュ・マップを短く ハッシュ hash )とよんだり、 マップ map )とよんだりします。 ここでは、ハッシュとよぶことにします。

注意: 他のプログラミング言語では、ハッシュのことを、 連想配列 associative array )や 辞書 dictionary )などとよびます。

1つのハッシュの中で、キーのデータ型はすべて同じで、さらに、参照データ型でなくてはなりません。 値のデータ型もすべて同じで、参照データ型でなくてはなりません。 ただし、キーのデータ型と値のデータ型は、違ってもよいです。

配列やリストは、添字が要素の順番を表していました。 それに対して、ハッシュには添字がありませんので、順番もありません。

ハッシュの使い方

以下はハッシュのプログラムの例です。

HashTest.java
/*  1*/ import java.util.*;
/*  2*/ 
/*  3*/ class HashTest { // ハッシュのテスト
/*  4*/     public static void main (String[] args) {
/*  5*/         HashMap<String, Integer> hash = new HashMap<String, Integer>(); // 宣言と生成
/*  6*/         hash.put("tea", 150); // 追加
/*  7*/         hash.put("coffee", 120); // 追加
/*  8*/         hash.put("water", 100); // 追加
/*  9*/         System.out.println(hash); // すべて出力
/* 10*/     }
/* 11*/ }
コンソール
{tea=150, coffee=120, water=100}

Completed with exit code: 0

プログラムでハッシュを扱うときは、先頭に

import java.util.*;

と書きます。

ハッシュのための変数を宣言するには、

HashMap<キーのデータ型, 値のデータ型> ハッシュ名;

と書きます。 ハッシュを生成して変数に代入するには、

ハッシュ名 = new HashMap<キーのデータ型, 値のデータ型>();

と書きます。

なお、宣言と生成は、

HashMap<キーのデータ型, 値のデータ型> ハッシュ名 = new HashMap<キーのデータ型, 値のデータ型>();

とまとめられます。

宣言・生成のときの、キーのデータ型や値のデータ型は、整数だったり文字列だったりします。

例えば、「teaの値段は120円です。」のように、商品名と値段の対応をハッシュにしたければ、文字列「tea」と整数「120」を対応させればよいので、

HashMap<String, Integer> hash = new HashMap<String, Integer>();

と宣言・生成します。

「1970年に大阪万博がありました。」のように、歴史年表をハッシュにしたければ、整数「1970」と文字列「大阪万博」を対応させればよいので、

HashMap<Integer, String> hash = new HashMap<Integer, String>();

と宣言・生成します。

「redの意味は赤です。」のように、英和辞典をハッシュにしたければ、文字列「red」と文字列「赤」を対応させればよいので、

HashMap<String, String> hash = new HashMap<String, String>();

と宣言・生成します。

ハッシュにキーと値の対応を追加するには、

ハッシュ名.put(キー, );

と書きます。 これで、「ハッシュ名」に「キー」と「値」の対応が追加されます。 これを繰り返せば、複数のキーと値の対応があるハッシュになります。

ハッシュのすべてのキーと値の対応を確認するには、

System.out.println(ハッシュ名);

と書きます。 これで、ブレース括弧に囲まれたキーと値の対応の並びが出力されます。

ハッシュにキーと値の対応があれば、キーを指定して、値を代入したり、値を取得したりできます。

HashPutGet.java
/*  1*/ import java.util.*;
/*  2*/ 
/*  3*/ class HashPutGet { // ハッシュに対する代入と取得
/*  4*/     public static void main (String[] args) {
/*  5*/         HashMap<String, Integer> hash = new HashMap<String, Integer>();
/*  6*/         hash.put("milk", 250); // 追加
/*  7*/         hash.put("juice", 400); // 追加
/*  8*/         hash.put("juice", 380); // 代入
/*  9*/         System.out.println(hash.get("milk")); // 取得
/* 10*/         System.out.println(hash.get("juice")); // 取得
/* 11*/         System.out.println(hash.get("cocoa")); // 存在しない
/* 12*/     }
/* 13*/ }
コンソール
250
380
null

Completed with exit code: 0

「キー」に対応する「値」を代入するには、

ハッシュ名.put(キー, );

と書きます。 追加と代入が同じ put() ですが、キーに対応する値がなければ追加、あれば代入になります。

「キー」に対応する値を取得するには、

ハッシュ名.get(キー)

と書きます。 もし、「キー」に対応する値がなければnullという値になります。

「キー」に対応する値を削除するには、

ハッシュ名.remove(キー);

と書きます。

HashRemove.java
/*  1*/ import java.util.*;
/*  2*/ 
/*  3*/ class HashRemove { // ハッシュからの削除
/*  4*/     public static void main (String[] args) {
/*  5*/         HashMap<String, Integer> hash = new HashMap<String, Integer>();
/*  6*/         hash.put("milk", 250); // 追加
/*  7*/         hash.put("juice", 400); // 追加
/*  8*/         hash.remove("juice"); // 削除
/*  9*/         System.out.println(hash);
/* 10*/     }
/* 11*/ }
コンソール
{milk=250}

Completed with exit code: 0

リストとハッシュの使用例

リストの例として、プログラムの実行中に次々と文字列を入力し、それらを覚える、というものを考えます。 以前、配列を使ったときは、要素の追加ができないので、あらかじめ大きな配列を用意したりしました。 リストを使えば、要素の追加できるので、そのようなことをしなくてもよいのです。

データの終了の目印として、 end と入力してもらうことにします。 文字列の比較は == ではなく equals() であることを思い出してください。

ListInput.java
/*  1*/ import java.io.*;
/*  2*/ import java.util.*;
/*  3*/ 
/*  4*/ class ListInput { // リストへの入力
/*  5*/     public static void main (String[] args) throws IOException {
/*  6*/         InputStreamReader isr = new InputStreamReader(System.in);
/*  7*/         BufferedReader br = new BufferedReader(isr);
/*  8*/         int i;
/*  9*/         String input;
/* 10*/         ArrayList<String> list = new ArrayList<String>(); // 文字列のリスト
/* 11*/         System.out.println("終了はendを入力してください。");
/* 12*/         while (true) { // 無限ループ
/* 13*/             System.out.print("文字列を入力してください: ");
/* 14*/             input = br.readLine(); // データの入力
/* 15*/             if (input.equals("end")) { // データの終了
/* 16*/                 break;
/* 17*/             }
/* 18*/             list.add(input); // データの追加
/* 19*/         }
/* 20*/         for (i = 0; i < list.size(); i++) { // リストの要素数回繰り返す
/* 21*/             System.out.println(list.get(i)); // データの取得
/* 22*/         }
/* 23*/     }
/* 24*/ }
コンソール
終了はendを入力してください。
文字列を入力してください: red
文字列を入力してください: blue
文字列を入力してください: yellow
文字列を入力してください: end
red
blue
yellow

Completed with exit code: 0

ハッシュの使用例として、商品名を入力すると値段が表示されるプログラムを考えます。

プログラムでは、商品名と値段の対応をハッシュに追加してから、商品名を聞きます。 入力された商品名がハッシュになければ、値がnullになりますが、それを判定するには、値と null == で比較します。

HashAccess.java
/*  1*/ import java.io.*;
/*  2*/ import java.util.*;
/*  3*/ 
/*  4*/ class HashAccess { // ハッシュへのアクセス
/*  5*/     public static void main (String[] args) throws IOException {
/*  6*/         InputStreamReader isr = new InputStreamReader(System.in);
/*  7*/         BufferedReader br = new BufferedReader(isr);
/*  8*/         String input;
/*  9*/         Integer value;
/* 10*/         HashMap<String, Integer> hash = new HashMap<String, Integer>();
/* 11*/         hash.put("tea", 150); // 追加
/* 12*/         hash.put("coffee", 120); // 追加
/* 13*/         hash.put("water", 100); // 追加
/* 14*/         System.out.print("商品名を入力してください: ");
/* 15*/         input = br.readLine(); // データの入力
/* 16*/         value = hash.get(input); // 値の取得
/* 17*/         if (value == null) { // ハッシュになければ
/* 18*/             System.out.println(input + "の値段は分かりません。");
/* 19*/         } else {
/* 20*/             System.out.println(input + "の値段は" + value + "円です。");
/* 21*/         }
/* 22*/     }
/* 23*/ }
コンソール
商品名を入力してください: tea
teaの値段は150円です。

Completed with exit code: 0
コンソール
商品名を入力してください: cider
ciderの値段は分かりません。

Completed with exit code: 0

演習15

ハッシュを利用して、小さな英和辞典を作成してください。 まず、「red」と「赤」の対応、「blue」と「青」の対応、「yellow」と「黄色」の対応を、ハッシュに追加します。 そして英単語を入力してもらい、ハッシュにその英単語があれば意味を出力し、なければ分からないと出力します。

SmallDictionary.java
import java.io.*;
import java.util.*;

class SmallDictionary {
    public static void main (String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);



    }
}
コンソール
英単語を入力してください: red
redの意味は赤です。

Completed with exit code: 0
コンソール
英単語を入力してください: green
greenの意味は分かりません。

Completed with exit code: 0

余力のある人は、1回で終わるのではなく、 end と入力されるまで何度も繰り返すようにしてください。

コンソール
終了はendを入力してください。
英単語を入力してください: red
redの意味は赤です。
英単語を入力してください: green
greenの意味は分かりません。
英単語を入力してください: end

Completed with exit code: 0

レポート課題

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


提出期限

すべてのレポートの提出期限を、1月30日(火)とします。


参考文献


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

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