HashTableの使用と原理

7066 ワード

一、---使い方---
(1)Hashtableはばらばらなリストであり、その内容はキーパッド対(key-value)マッピングである。
(2)Hashtable Dictoraryに引き継がれ、Map、Cloeable、java.io.Serializableインターフェースを実現しました。
(3)Hashtableの関数は同期しています。これはスレッドが安全であることを意味します。そのkey、valueは全部nullではいけません。
以下のように、Hashtableの簡単な使い方です。遍歴は三つの方法で行います。
package ThreeWeek;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

public class HashTableTest {

	public static void main(String args[]){
		Hashtable table = new Hashtable();
		
		//[1]    
		table.put("zhangsan", 22);
		table.put("lisi", 33);
		table.put("wangwu", 44);
		
		//[2]toString()    
		System.out.println(table.toString());
		
		//[3]Iterator    1--     entrySet()
		Iterator> iter = table.entrySet().iterator();
		while(iter.hasNext()){
			Map.Entry entry = (Map.Entry)iter.next();
			String key = entry.getKey();
			int value = entry.getValue();
			System.out.println("entrySet:"+key+" "+value);
		}
		
		System.out.println("====================================");
		
		//[4]Iterator    2--key    
		Iterator iterator = table.keySet().iterator();
		while(iterator.hasNext()){
			String key = (String)iterator.next();
			int value = table.get(key);
			System.out.println("keySet:"+key+" "+value);
		}
		
		System.out.println("====================================");
		
		//[5]  Enumeration   Hashtable
		Enumeration enu = table.keys();
		while(enu.hasMoreElements()) {
		    System.out.println("Enumeration:"+table.keys()+" "+enu.nextElement());
		} 
			
	}
}
--------output----------------
{zhangsan=22, lisi=33, wangwu=44}
entrySet:zhangsan 22
entrySet:lisi 33
entrySet:wangwu 44
====================================
keySet:zhangsan 22
keySet:lisi 33
keySet:wangwu 44
====================================
Enumeration:java.util.Hashtable$Enumerator@139a55 zhangsan
Enumeration:java.util.Hashtable$Enumerator@1db9742 lisi
Enumeration:java.util.Hashtable$Enumerator@106d69c wangwu
二、---内部原理---
1、相続関係
java.lang.Object
   ↳     java.util.Dictionary
         ↳     java.util.Hashtable

public class Hashtable extends Dictionary
    implements Map, Cloneable, java.io.Serializable { }
HashMapとは違って、HashtableはDictoryを継承し、Mapインターフェースを実現しました。Mapは「key-valueキーペア」インターフェースで、Dictionaryは操作を宣言しました。
キー対数関数インターフェースの抽象的なクラスを作ります。 
2、コンストラクタ
(1)Hashtableには、次のような4つの構成関数が提供されています。
//       。
public Hashtable() 

//   “    ”     
public Hashtable(int initialCapacity) 

//   “    ” “    ”     
public Hashtable(int initialCapacity, float loadFactor) 

//   “ Map”     
public Hashtable(Map extends K, ? extends V> t)
(2)上の4つの構成方法のうち、3番目が最も重要であり、初期化容量と構造因子を指定する。
public Hashtable(int initialCapacity, float loadFactor) {  
        //        
        if (initialCapacity < 0)  
            throw new IllegalArgumentException("Illegal Capacity: "+  
                                               initialCapacity);  
        //        
        if (loadFactor <= 0 || Float.isNaN(loadFactor))  
            throw new IllegalArgumentException("Illegal Load: "+loadFactor);  
  
        if (initialCapacity==0)  
            initialCapacity = 1;  
          
        this.loadFactor = loadFactor;  
          
        //   table,     initialCapacity table    
        table = new Entry[initialCapacity];  
        //      
        threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);  
        //   HashSeed   
        initHashSeedAsNeeded(initialCapacity);  
    }  
3、メンバー変数
(1)テーブルはEntry[]配列タイプで、Entryは実は一方向チェーンです。ハッシュ表の「key-valueキーペア」はすべてEntry配列に格納されています。 
(2)countはhashtableの大きさで、hashtableに保存されているキーの数です。 
(3)threshtableはhashtableの閾値であり、Hashtableの容量を調整する必要があるかどうかを判断するために使用される。threshldの値=「容量*ローディング係数」。
(4)loadFactorとは、負荷係数である。
(5)modCountはfail-fast機構を実現するためのものである。
 private transient Entry[] table;
// Hashtable        
private transient int count;
//   ,          Hashtable   (threshold =   *    )
private int threshold;
//     
private float loadFactor;
// Hashtable      
private transient int modCount = 0;
4、putとget方法
(1)put方法
下記のコードからわかるように、Hashtableの中のkeyとvalueは空であることが許されません。Hashtableの中に元素を追加したい場合、まずkeyのhash値を計算します。
その後、hash値によってテーブル配列のインデックス位置を決定し、最後にvalue値を入れ替えたり、新しい要素を挿入したりします。容器の数が閾値に達したら、拡張します。
public synchronized V put(K key, V value) {  
        //   value  null  
        if (value == null) {  
            throw new NullPointerException();  
        }  
  
        /* 
         *   key table[]      
         *     : 
         * 1、  key hash ,   table[]       
         * 2、  index    ,                 key,    value,     
         */  
        Entry tab[] = table;  
        int hash = hash(key);    //  key hash   
        int index = (hash & 0x7FFFFFFF) % tab.length;     //   key       
        //  ,   key,    
        for (Entry e = tab[index] ; e != null ; e = e.next) {  
            if ((e.hash == hash) && e.key.equals(key)) {  
                V old = e.value;  
                e.value = value;  
                return old;  
            }  
        }  
  
        modCount++;  
        if (count >= threshold) {  //                ,         
            rehash();  
            tab = table;  
            hash = hash(key);  
            index = (hash & 0x7FFFFFFF) % tab.length;  
        }  
  
        //                 
        Entry e = tab[index];  
        tab[index] = new Entry<>(hash, key, value, e);  
        //     +1  
        count++;  
        return null;  
    }  
(2)get方法
同様に、インデックス値を先に取得し、巡回して、最後に戻ります。
public synchronized V get(Object key) {  
        Entry tab[] = table;  
        int hash = hash(key);  
        int index = (hash & 0x7FFFFFFF) % tab.length;  
        for (Entry e = tab[index] ; e != null ; e = e.next) {  
            if ((e.hash == hash) && e.key.equals(key)) {  
                return e.value;  
            }  
        }  
        return null;  
    }  
五、---比較的違う---
HashtableとHashMapはいったいどんな違いがありますか?
(1)基質の違い:HashTableはDictorary類に基づいていますが、HashMapはAbstractMapに基づいています。Dictionaryは何ですか?キーを対応する値にマッピングできるクラスの抽象的な親であり、AbstractMapはMapインターフェースのバックボーンに基づいて実現され、このインターフェースを実現するために必要な作業を最大限に減らす。
(2)nullは違っています。HashMapはnullというkeyとnullのいずれかのvalueが存在することができますが、HashTableの中のkeyとvalueはnullとしては許されません。
(3)スレッド安全:HashMap時に単一スレッドが安全であり、Hashtableはマルチスレッドが安全である。
(4)遍歴が違っています。HashMapはIteratorの遍歴のみをサポートしています。HashtableはIteratorとEnumerationの両方をサポートしています。
作者を尊重し、オリジナルを尊重し、文章を参考する:
http://www.cnblogs.com/skywang12345/p/3310887.html#a1
http://cmsblogs.com/?p=618