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

情報処理技法(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
import java.util.ArrayList;

class ListTest { // リストのテスト
    public static void main (String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>(); // 宣言と生成
        list.add(10); // 追加
        list.add(11); // 追加
        list.add(12); // 追加
        list.add(13); // 追加
        list.add(14); // 追加
        System.out.println(list); // すべて出力
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'ListTest'
[10, 11, 12, 13, 14]
PS ...\Desktop\java1>

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

import java.util.ArrayList;

と書きます。

整数(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
import java.util.ArrayList;

class ListSetGet { // リストに対する代入と取得
    public static void main (String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(100); // 追加
        list.add(101); // 追加
        list.set(1, 200); // 1番目に200を代入
        System.out.println(list.get(0)); // 0番目を取得
        System.out.println(list.get(1)); // 1番目を取得
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'ListSetGet'
100
200
PS ...\Desktop\java1>

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

リスト変数.set(添字, );

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

リスト変数.get(添字)

と書きます。

リストの要素数は、

リスト変数.size()

で分かります。

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

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

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

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

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

ListLoop.java
import java.util.ArrayList;

class ListLoop { // リストのループ
    public static void main (String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        for (int i = 0; i < 10; i++) { // 10回繰り返す
            list.add(0); // 最後に0を追加
        }
        for (int i = 0; i < list.size(); i++) { // リストの要素数回繰り返す
            System.out.println(list.get(i));
        }
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'ListLoop'
0
0
0
0
0
0
0
0
0
0
PS ...\Desktop\java1>

リストの初期化

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

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

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

import java.util.Arrays;

を追加します。

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

ListInitialize.java
import java.util.ArrayList;
import java.util.Arrays;

class ListInitialize { // リストの初期化
    public static void main (String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(
            20, 21, 22, 23, 24, 25, 26, 27, 28, 29
        )); // リストの初期化
        System.out.println(list);
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'ListInitialize'
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
PS ...\Desktop\java1>

リスト要素の追加と削除

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

リスト変数.add(添字, );

とします。

ListAdd.java
import java.util.ArrayList;
import java.util.Arrays;

class ListAdd { // リストの要素の追加
    public static void main (String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(
            10, 11, 12, 13, 14
        ));
        list.add(1, 20); // 1番目に20を追加
        System.out.println(list);
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'ListAdd'
[10, 20, 11, 12, 13, 14]
PS ...\Desktop\java1>

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

リスト変数.remove(添字);

とします。

ListRemove.java
import java.util.ArrayList;
import java.util.Arrays;

class ListRemove { // リストの要素の削除
    public static void main (String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(
            10, 11, 12, 13, 14
        ));
        list.remove(1); // 1番目を削除
        System.out.println(list);
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'ListRemove'
[10, 12, 13, 14]
PS ...\Desktop\java1>

ハッシュ

ハッシュとは

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

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
import java.util.HashMap;

class HashTest { // ハッシュのテスト
    public static void main (String[] args) {
        HashMap<String, Integer> hash = new HashMap<String, Integer>(); // 宣言と生成
        hash.put("tea", 150); // 追加
        hash.put("coffee", 120); // 追加
        hash.put("water", 100); // 追加
        System.out.println(hash); // すべて出力
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'HashTest'
{tea=150, coffee=120, water=100}
PS ...\Desktop\java1>

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

import java.util.HashMap;

と書きます。

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

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
import java.util.HashMap;

class HashPutGet { // ハッシュに対する代入と取得
    public static void main (String[] args) {
        HashMap<String, Integer> hash = new HashMap<String, Integer>();
        hash.put("milk", 250); // 追加
        hash.put("juice", 400); // 追加
        hash.put("juice", 380); // 代入
        System.out.println(hash.get("milk")); // 取得
        System.out.println(hash.get("juice")); // 取得
        System.out.println(hash.get("cocoa")); // 存在しない
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'HashPutGet'
250
380
null
PS ...\Desktop\java1>

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

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

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

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

ハッシュ変数.get(キー)

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

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

ハッシュ変数.remove(キー);

と書きます。

HashRemove.java
import java.util.HashMap;

class HashRemove { // ハッシュからの削除
    public static void main (String[] args) {
        HashMap<String, Integer> hash = new HashMap<String, Integer>();
        hash.put("milk", 250); // 追加
        hash.put("juice", 400); // 追加
        hash.remove("juice"); // 削除
        System.out.println(hash);
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'HashRemove'
{milk=250}
PS ...\Desktop\java1>

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

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

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

ListInput.java
import java.util.ArrayList;
import java.util.Scanner;

class ListInput { // リストへの入力
    public static void main (String[] args) {
        Scanner stdIn = new Scanner(System.in);
        String input;
        ArrayList<String> list = new ArrayList<String>(); // 文字列のリスト
        System.out.println("終了はendを入力してください。");
        while (true) { // 無限ループ
            System.out.print("文字列を入力してください: ");
            input = stdIn.nextLine(); // データの入力
            if (input.equals("end")) { // データの終了
                break;
            }
            list.add(input); // データの追加
        }
        for (int i = 0; i < list.size(); i++) { // リストの要素数回繰り返す
            System.out.println(list.get(i)); // データの取得
        }
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'ListInput'
終了はendを入力してください。
文字列を入力してください: red
文字列を入力してください: blue
文字列を入力してください: yellow
文字列を入力してください: end
red
blue
yellow
PS ...\Desktop\java1>

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

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

HashAccess.java
import java.util.HashMap;
import java.util.Scanner;

class HashAccess { // ハッシュへのアクセス
    public static void main (String[] args) {
        Scanner stdIn = new Scanner(System.in);
        String input;
        Integer value;
        HashMap<String, Integer> hash = new HashMap<String, Integer>();
        hash.put("tea", 150); // 追加
        hash.put("coffee", 120); // 追加
        hash.put("water", 100); // 追加
        System.out.print("商品名を入力してください: ");
        input = stdIn.nextLine(); // データの入力
        value = hash.get(input); // 値の取得
        if (value == null) { // ハッシュになければ
            System.out.println(input + "の値段は分かりません。");
        } else {
            System.out.println(input + "の値段は" + value + "円です。");
        }
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'HashAccess'
商品名を入力してください: tea
teaの値段は150円です。
PS ...\Desktop\java1>
ターミナル
PS ...\Desktop\java1>  & ... 'HashAccess'
商品名を入力してください: cider
ciderの値段は分かりません。
PS ...\Desktop\java1>

演習15

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

SmallDictionary.java
import java.util.HashMap;
import java.util.Scanner;

class SmallDictionary {
    public static void main (String[] args) {
        Scanner stdIn = new Scanner(System.in);
        
        
        
    }
}
ターミナル
PS ...\Desktop\java1>  & ... 'SmallDictionary'
英単語を入力してください: red
redの意味は赤です。
PS ...\Desktop\java1>
ターミナル
PS ...\Desktop\java1>  & ... 'SmallDictionary'
英単語を入力してください: green
greenの意味は分かりません。
PS ...\Desktop\java1>

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

ターミナル
PS ...\Desktop\java1>  & ... 'SmallDictionary2'
終了はendを入力してください。
英単語を入力してください: red
redの意味は赤です。
英単語を入力してください: green
greenの意味は分かりません。
英単語を入力してください: end
PS ...\Desktop\java1>

レポート課題

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


提出期限

すべてのレポートの提出期限を2025年8月1日(金)とします。


参考文献


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

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