hashTable和hashMap區別

Hashtable HashMap 作爲 Map 的基本特性
二者都實現了Map接口,基本特性相同
-          對同一個Key,只會有一個對應的value值存在
-          如何算是同一個Key? 首先,兩個key對象的hash值相同,其次,key對象的equals方法返回真
內部數據結構
Hashtable和HashMap的內部數據結構類似

 
其基本內部數據結構是一個Entry數組 ( transient Entry[] table)
-          數組元素爲實現Map.Entry<K,V>接口的類,Hashtable和HashMap各自實現了本身的Entry類。
-          Entry包含一個Key-value對,以及一個next指針指向另外一個Entry。多個Entry能夠組成一個單向鏈表。
經常使用操做
數據插入操做: put(key,value)
-          根據Key的hash值計算出該Entry所應存放的位置(數組下標)
-          若該數組元素爲空,直接放置Entry到此處
-          若多個不一樣的Key所計算獲得的數組下標相同,新加入的Key-value對(Entry)會被加入到Entry單向鏈表中。Hashtable和HashMap都是將其插入鏈表首部.
-          若已經有相同的Key存在於這個鏈表中,則,新的value值會取代老的value
-          當Map中存放的Entry數量超過其限制( 數組長度 * 負荷因子)時,Map將自動從新調整數組大小並從新對Entry進行散列
 
 
數據查找:get(key)
-          根據Key的hash值計算出該Entry對所應存放的位置(數組下標)
-          獲得該位置的第一個Entry對象,比較key和Entry.key,若hash值相同,而且equals爲真,則該Entry是咱們要找的Key-value對,不然繼續沿next指針構成的單向鏈表查找
 
數據移除:remove(key)
-           按照上述數據查找的方式找到key所在的Entry對象,將其移除,並保持Entry單向鏈表的連通性
Hashtable HashMap 的比較

 

 
Hashtable
HashMap
併發操做
使用同步機制,
實際應用程序中,僅僅是Hashtable自己的同步並不能保證程序在併發操做下的正確性,須要高層次的併發保護。
下面的代碼試圖在key所對應的value值等於x的狀況下修改value爲x+1
{
 value = hashTable.get(key);
   if(value.intValue()== x){
hashTable.put(key,      new Integer(value.intValue()+1));
   }
}
如2個線程同時執行以上代碼,可能放入不是x+1,而是x+2.
沒有同步機制,須要使用者本身進行併發訪問控制
數據遍歷的方式
Iterator 和 Enumeration
Iterator
是否支持fast-fail
用Iterator遍歷,支持fast-fail
用Enumeration不支持fast-fail.
支持fast-fail
是否接受值爲null的Key 或Value?
不接受
接受
根據hash值計算數組下標的算法
當數組長度較小,而且Key的hash值低位數值分散不均勻時,不一樣的hash值計算獲得相同下標值的概率較高
 
hash = key.hashCode();
index=(hash&0x7FFFFFFF) % tab.length;
優於hashtable,經過對Key的hash作移位運算和位的與運算,使其能更普遍地分散到數組的不一樣位置
 
hash = hash (k);
index = indexFor(hash, table.length);
 
static int hash(Object x) {
 int h = x.hashCode();
h += ~(h << 9);
 h ^= (h >>> 14);
  h += (h << 4);
 h ^= (h >>> 10);
 return h;
}
static int indexFor(int h, int length) {
return h & (length-1);
}
 
Entry數組的長度
Ø         缺省初始長度爲11,
Ø         初始化時能夠指定initial capacity
Ø         缺省初始長度爲16,
Ø         長度始終保持2的n次方
Ø         初始化時能夠指定initial capacity,若不是2的次方,HashMap將選取第一個大於initial capacity 的2n次方值做爲其初始長度
LoadFactor負荷因子
0.75
負荷超過(loadFactor * 數組長度)時,內部數據的調整方式
擴展數組:2*原數組長度+1
擴展數組: 原數組長度 * 2
二者都會從新根據Key的hash值計算其在數組中的新位置,從新放置。算法類似,時間、空間效率相同
 
通常狀況下,HashMap可以比Hashtable工做的更好、更快,主要得益於它的散列算法,以及沒有同步。應用程序通常在更高的層面上實 現了保護機制,而不是依賴於這些底層數據結構的同步,所以,HashMap可以在大多應用中知足須要。推薦使用HashMap,若是須要同步,可使用同 步工具類將其轉換成支持同步的HashMap。
Map的效率
Map的效率與Entry數組大小及負荷因子的選取有密切關係。選取適當的數組大小有利於Key-value對的散列分佈,而且,若是數組足夠 大,將有效的減小從新調整數組的次數,提升效率。較小的負荷因子將佔用更多的空間,但下降衝突的可能性,從而將加快訪問和更新的速度。
另外,Key的hash值自己若是能保證較好的散列性,也有益於提升Map的讀寫效率。在effective java中,對hash()的重載有好的建議。
關於如何提升Map的執行效率,可參考《Java Map 集合類簡介》 http://www.oracle.com/technology/global/cn/pub/articles/maps1.html
 
辨析
  「Hashtable和HashMap的區別主要是前者是同步的,後者是快速失敗機制保證不會出現多線程併發錯誤(Fast-Fail)。」,這是一個被不少文章轉載過的概念,但其描述並不許確,容易引發誤會。
實質上,Fast-fail與同步保護的是兩種不一樣狀況下的併發,二者不能拿來作比較。
Hashtable是同步的,在執行get,put,remove,size,clear等一次性讀寫操做時,使用了同步機制,避免了多個線程 同時讀寫Hashtable。但同步機制並不能避免在iterator或Enumeration遍歷過程當中其餘線程對Hashtable的put、 remove、clear操做,這些寫操做都會被毫無阻攔得成功執行。
快速失敗機制主要目的在於使iterator遍歷數組的線程能及時發現其餘線程對Map的修改(如put、remove、clear等),因 此,fast-fail並不能保證全部狀況下的多線程併發錯誤,只能保護iterator遍歷過程當中的iterator.next()與寫併發.
其次,Hashtable的iterator遍歷方式也是支持fast-fail的,不能說它沒有快速失敗機制。寫一個簡單的例程就能夠證實這 一點,一個線程作iterator遍歷,另外一個線程向hashtable中put新的key和value,很容易就會觀察到fast-f ail 機制報告 ConcurrentModificationException
原文:http://www.cnblogs.com/carbs/archive/2012/07/04/2576995.html
相關文章
相關標籤/搜索