サブゼミ第8回

サブゼミ第8回
実装編②HashTable,JavaAPI
Objective



連想配列(ハッシュテーブル)の概念を利
点欠点を明らかにしながら説明できるよう
になる
ハッシュテーブルを使ったプログラムが書
けるようになる
JavaAPIを使ったプログラムが書けるよう
になる
前回のモデル
・配列を管理するクラスを導入したクラス図
このままでは追加と表示しかできません
検索するには
☆例えば、商品番号1055の価格が知りたい場合
番号=1001
商品名="コーラ"
価格=150
番号=1055
商品名="DDレモン"
価格=120
番号=1022
商品名="ソーダ"
価格=140
[1]
[2]
[3]
配列を順繰りにたどって探す(リニアサーチ)
しかし遅いO(N)
[4]
検索するには
☆例えば、商品番号1055の価格が知りたい場合
番号=1001
商品名="コーラ"
価格=150
番号=1022
商品名="ソーダ"
価格=140
番号=1055
商品名="DDレモン"
価格=120
[1]
[2]
[3]
商品番号順にならんでいれば(バイナリサーチ)
なかなか速いO(logN)
[4]
でも実用性がない
☆商品番号1055の価格が知りたい
ということはあまりなく
☆DDレモンの価格が知りたい
という使い方をしたい
商品名で検索する
☆例えば、DDレモンの価格が知りたい場合
番号=1001
商品名="コーラ"
価格=150
番号=1022
商品名="ソーダ"
価格=140
番号=1055
商品名="DDレモン"
価格=120
[1]
[2]
[3]
配列を順繰りにたどって探す(リニアサーチ)
しかし遅いO(N)
ではどのように検索したらよいのか
[4]
どのように検索したら
速くなるのか


現状の問題点を整理しよう
早くするためのアイディアを考えよう
こんなのが欲しい
list[0].getPrice()
list[1].getPrice()
list["コーラ"].getPrice()
list["DDレモン"].getPrice()
このような配列を
「連想配列」(ハッシュテーブル)
といいます。
perlなどでは標準でできる
Javaでは、そのようなオブジェクト
を作る
ハッシュテーブルを作るには

まず、文字として扱っている間は、コン
ピュータでは検索できないので、何らかの
数字に変換します。

インデックスシング、ハッシング
例えば、こんなやり方があります(詳しくは専門書を見て)
変換表
コ 98
- 103
ラ 67
コーラ
→
9810367
大きい配列を作る!?
コーラ
→
9810367
これをそのまま配列のインデックスにしようとすると、相当大きい
配列が必要
list[9810367].getPrice()
→現実的ではない
小さい配列で済むためには

1000要素の配列で済ませることを考える
コーラ
→
9810367
→
367
プログラムで9810367→367と変換するには
9810367%1000
(1000で割ったあまりを求める)
ハッシュ関数

高速検索できるように、文字列から、一定
範囲の数字を求める関数のこと



詳しくは「アルゴリズムとデータ構造」を見てみ
よう
今回の説明でのまずいところを発見しよう
JavaではObjectクラスにhashcode()メソッ
ドがあるので、どんなオブジェクトでも、簡
単に求めることができます。
衝突が起こる

違うオブジェクトが同じハッシュ値になる可
能性がある
コーラ
ソーダ
→
→
31256448
587648448
→
→
448
448
衝突回避①
空き番地法(線形探索)
1
2
3
4
ソーダも入りた
い!
447
・・・・・
448
コーラ
449
ソーダ
500
DDレモン
もし計算されたアドレスにすでにデータが格納されていた場合
次のアドレスにデータを格納する。
次も格納されていたらさらに次のアドレスに格納しようとする
検索するときにはハッシュ値を求めた後、そのアドレスから
順に配列の中身をリニアサーチで調べる
空き番地法(線形探索)の問題点

クラスター化
1
2
3
4
→平方探索に変えると第2種クラスター化
→クラスター化を防ぐためにダブルハッシュ
などの技法を使う必要あり
5
6
7
8
9
10
11
12
13
衝突回避②
分離連鎖法
1
2
3
4
447
・・・・・
448 コーラ
ソーダ
DDレモン
449
500
衝突したら、そのアドレスからさらに連結リストを使ってデータを
格納しておく方法
検索するときにはハッシュ値を求めた後、そのアドレスから
順に連結リストを使って調べる
ハッシュテーブルの
利点、欠点を考えてみよう
ハッシュテーブルの概念整理
key
”コーラ”
”ソー
ダ”
”お茶”
”DD”
value
辞書、住所録みたいなものに
colaObject
sodaObject
chaObject
ddObject
適している
青山
090-xxx-xxxxx
海保
090-xxx-xxxxx
高嶋
090-xxx-xxxxx
松澤
070-xxx-xxxxx
ハッシュテーブルの問題点
•データの保持に内部的には配列を使用するので
事前に用意した配列が満杯に近づいてくると
検索、挿入の効率が格段に落ちる
•保持するデータを昇順や降順に
ソートして取り出すといった機能はない
高速な検索が必要で確保するべきデータ量が
ある程度予測できる場合に使う
JavaAPIを利用する

API

Application Programming Interface
アプリケーションを作るためによく使う機能を提供するプログラム
→ライブラリ
Javaでは関数群ではなく、よく使われるクラスの集まりと考えればよい
Swingや、Servletなどもそれに当たります。
APIを使おう
配列で作ったリスト、連結リスト、ハッシュテーブルなどは良く使うので、
既に作られている。
List
ArrayList
配列で実装された
リストクラス
LinkedList
連結リストで実装された
リストクラス
APIを利用した設計
自動販売機
<<クラス図>>
商品情報型
- 商品名 : String
- 商品情報ID : int
- 価格 : int
取扱商品型
+ 商品追加()
+ 商品表示() 1
+ 検索()
VendingMachine
Appli
0..n + get価格()
+ get商品情報ID()
+ get商品名()
ArrayList
(java.util から)
取扱貨幣型
+ 貨幣追加()
+ 貨幣表示() 1
貨幣情報型
- 貨幣情報ID : int
- 価値 : int
0..n + get価値()
+ get貨幣情報ID()
Listの使い方
特徴
データを順番に並べて格納する
格納するデータは重複してもかまわない
主な実装クラス ArrayList・・・単方向リストを配列で実装したもの
LinkedList・・・配列で実装した連結リスト
主なメソッド
add(Object)・・・リストにオブジェクトを追加する
get(int)・・・リストから引数の位置にある
要素を取り出す
remove(Object)・・・指定された要素を削除
size()・・・リストの要素数を返す
iterator()・・・リストのIteratorを返す
使い方を調べる
JavaAPIドキュメント
Javaが提供する多くのクラスとその属性や操作を一つにまとめた
マニュアルのようなもの。
これを使えば知らない機能や
知らないクラスなども調べて使うことができます。
メソッドの使い方を忘れてしまったり、知らない機能を
追加したいときはまずAPIを見てみる癖をつけましょう!
http://java.sun.com/j2se/1.3/ja/docs/ja/api/index.html
Listを使った実装ー定義ー
import java.util.*;
public class 取扱商品型 {
private List 商品情報リスト;//取り扱う商品情報のリスト
/**
* コンストラクタ
*/
public 取扱商品型() {
商品情報リスト=new ArrayList();//ArrayListを初期化する
}
Listを使った実装ー追加ー
/**
* 取扱商品に商品情報を追加するメソッド
*/
public void 商品追加(商品情報型 追加商品情報){
商品情報リスト.add(追加商品情報);
}
Listを使った実装ー検索ー
/**
* 商品を商品名で検索するメソッド
*/
public 商品情報型 検索(String 検索名){
//リニアサーチ!こんなプログラムは実際には書くなよ。-->Hashでね
int len = 商品情報リスト.size();
for(int i=0;i<len;i++){
商品情報型 商品情報 = (商品情報型)商品情報リスト.get(i);
if(商品情報.get商品名().equals(検索名)){//見つかった
return 商品情報;
}
}
return null;//見つからなかった
}
Listを使った実装ー表示ー
/**
* 登録されているすべての商品情報の商品名とID、価格を出力するメソッド
*/
public void 商品表示(){
int len = 商品情報リスト.size();
for(int i=0;i<len;i++){
商品情報型 商品情報 = (商品情報型)商品情報リスト.get(i);
System.out.println(商品情報.get商品名()+" "+商品情報.get商品価格()+"円");
}
}
Collectionフレームワーク
java.utilパッケージの
クラス図
Collection
List
ArrayList
Set
LinkedList
SortedSet
Map
HashSet
HashMap
TreeMap
今週の課題①

APIドキュメントを読んで、



CollectionクラスとCollectionsクラスの違いを
説明しなさい
JavaAPIを使ってソートする方法を調べなさい。
そしてそのソートはどんなアルゴリズムを使っ
ているか答えなさい
スタック、キューを作るにはどのクラスをどん
な風に使えばよいのか調べなさい
今週の課題②
先週配布したソースコードを
改良して取扱商品は
HashMapを使い、取扱貨幣は
ArrayListを使ってデータを
格納するように改良してください。
また取扱商品には検索()メソッドを
追加してください。
必ずHashMapのAPIを調べてから行うこと。
課題のために

APIドキュメントとスケルトン(持ってない人
は)ここからダウンロードも可能です
http://nautilus.crew.sfc.keio.ac.jp/seminar/2001fall2/sub8/
発展課題

HashMapのソースコードを読んで、
実装が、「空き番地法」「分離連鎖法」のど
ちらでなされているかを答えなさい。
冬休みの課題

自分の作るシステムをCUIベースのアプリ
ケーションで完成させてください。


自動販売機CUIバージョンをメールで送ります
ので参考にして下さい
CUIができれば、Webアプリにするのはあとは
そう難しくありません