(1) Javaでハッシュ値を計算する方法について
(1-1) ハッシュを使った探索の概要
(1-2) ハッシュからアドレスを計算する方法
(1-3) サンプルプログラム
(1) Javaでハッシュ値を計算する方法について
(1-1) ハッシュを使った探索の概要
ハッシュを使った探索では「キー」となる値に対応したハッシュ値を求め、その値から求まるアドレス(下図ではindexという)にデータを格納していきます。
(図111)イメージ図
ハッシュを求め、そこから格納アドレスを計算する
(1-2) ハッシュからアドレスを計算する方法
(構文)
int index = (hash & 0x7fffffff) % [定数];
各値の内容は以下の表の通りです。
(表)構文の各値の内容
項目 | 説明 |
index | ハッシュから計算したアドレスです。配列のindex番目の要素に、値を格納していきます。 |
hash | ハッシュの値です。これはStringクラスの「hashCode」メソッドにより計算します。
(例) |
& 0x7fffffff | ハッシュの計算で目にする「& 0x7fffffff」は、インデックス(アドレス)にマイナスの数が入るのを防ぐための「ビットマスク」です。
後半の「0x7fffffff」のうち「0x」は「16進数である」事を表しており、「7fffffff」は16進数で表現された「32ビットの整数」です。これを「2進数」に変換すると、0の後に1が31個続き「01111111111111111111111111111111」となります。このとき一番左端の「0」のビットが「符号ビット」で、符号の情報を表しています(プラスは0、マイナスは1)。 (図)16進数⇒2進数への変換 前半の「&」を前に付けて「& 0x7fffffff」とする事で、先頭のビットのみ0をセットする、つまり符号を「必ずプラスにする」処理になります。 |
% [定数] | [定数]で割った余りを、最終的な格納アドレスにしています。そのため、配列は[定数]の数だけ要素を確保しておけば、OutOfRangeを防ぐ事ができます。 |
(図121)ハッシュの取得
(1-3) サンプルプログラム
実際にハッシュから計算したアドレスの要素に、値を格納するプログラムをご紹介します。
(概要)
Fruitクラスというフルーツの「名前」と「個数」を格納するクラスと、そのFruit型の配列「fruitmix」があります。そしてfruitmixにFruit型のインスタンスの要素を追加&取得する際には「put」と「get」メソッドを使います。このputとgetではそれぞれ格納・取得のアドレスをハッシュから計算しています。
(図131)
(サンプルプログラム)
public class IT0XXX_HashCodeTest3 { public static void main(String args[]) { CustomHashMap5 cm = new CustomHashMap5(1000); cm.put("Apple", 15); cm.put("Banana", 20); cm.put("Melon", 10); System.out.println("Quantity of Apple : "+cm.get("Apple")); System.out.println("Quantity of Banana : "+cm.get("Banana")); System.out.println("Quantity of Melon : "+cm.get("Melon")); } } class CustomHashMap5 { //【メンバ変数】 public Fruit[] fruitsmix; int mapsize; //【コンストラクタ】CustomHashMapのコンストラクタ public CustomHashMap5(int mapsize) { this.fruitsmix = new Fruit[mapsize]; this.mapsize = mapsize; } //【値の更新】Fruitクラスのインスタンスを更新 public void put(String w, int c) { //単語のインデックスを計算 int index = (w.hashCode() & 0x7fffffff) % mapsize; //インデックスの要素がnullの場合 →新規追加 if(fruitsmix[index]==null) { fruitsmix[index] = new Fruit(w,c); } //インデックスの要素がnullでない場合 →既存更新 else { fruitsmix[index].setValue(c); } } //【値の取得】キーからインデックスを計算して値を取得 public int get(String w) { int index = (w.hashCode() & 0x7fffffff) % mapsize; //インデックスの要素がnullの場合 →未使用の要素のため0を返却 if(fruitsmix[index]==null) { return 0; } //インデックスの要素がnullでない場合 →使用中の要素のためカウンタの値を返却 else { return fruitsmix[index].getValue(); } } //【クラス】Fruitsクラス class Fruit { private String fruits; //Key private int price; //Value public Fruit(String w, int c) {fruits = w; price = c;} public String getKey() {return fruits;} public int getValue() {return price;} public void setValue(int c) {price = c; } } }
(図)実行結果