程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 幾個集合類的比較

幾個集合類的比較

編輯:C++入門知識

幾個集合類的比較


1.Hashtable和HashMap

不同點總結如下

① Hashtable是Dictionary的子類,實現了Map接口;HashMap是AbstractMap的子類,是Map接口的一個實現類;


② Hashtable中的方法是同步的,大多數方法如put, get都用用synchronized關鍵字修飾。而HashMap是線程不安全的。在多線程程序中,可以不添加額外操作就可以安全的使用Hashtable,而對HashMap,則需要額外的同步機制,可以使用Collections的一個靜態方法解決:

Map Collections.synchronizedMap(Map m)
這個方法返回一個支持同步(線程安全)的Map對象,實質上是用synchronized封裝了HashMap的所有方法。


③在Hashtable中,key和value均不允許為null;而HashMap中,null可以作為key,也可以作為value,null作為key的時候,這樣的鍵只能有一個,但是可以有一個或多個鍵所對應的值為null,當調用HashMap的get方法的時候如果返回null,可以表示HashMap中沒有該鍵,也可以表示該鍵所對應的值為null,因此,在HashMap中不能由get方法來判斷是否存在某個鍵,而應該用containsKey方法來判斷。


④Hashtable中hash數組默認大小是11,增加方式是old*2+1;HashMap中的hash數組默認大小是16,新的容量是原來的2倍;


⑤哈希值的使用不同,Hashtable使用hashSeed與key.hashCode的異或運算的方法:

int hash = hashSeed ^ key.hashCode()
int index = (hash & 0x7FFFFFFF) % tab.length;
而HashMap並不是直接將對象的hashCode作為哈希值的,而是要把key的hashCode作一些運算以得到最終的哈希值,並且得到的哈希值再和數組長度按位與運算才得到在數組中的位置。

內部實現

在Java中,Hashtable和HashMap的內部結構都是采用Entry數組來實現,一個Entry類包含四個成員變量:hash、key、value、next。

\

從上圖中我們可以看到,哈希表是有數組+鏈表組成的,一個長度為16的數組中,每個元素存儲的是一個鏈表的頭結點,這些元素通過hash(key)%len,也就是key的哈希值對數組長度取模得到應該放入的數組位置下標。例如上述哈希表中,12%16=12,28%16=12,108%16=12,140%16=12,所以12、28、108、140都存儲在數組下標為12的位置。<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+19y94c/CSGFzaE1hcNDC1PZwdXS6zbvxyKFnZXSy2df3o7o8L3A+CjxwPjxwcmUgY2xhc3M9"brush:java;">//存儲時: int hash = key.hashCode(); int i = hash % Entry[].length; Entry[i] = value; //取值時: int hash = key.hashCode(); int i = hash % Entry[].length; return Entry[i];


注意:

如果數據大小是固定的,那麼最好給HashMap設定一個合理的容量值。HashMap的初始默認容量是16,默認加載因子是0.75,也就是說,如果采用HashMap的默認構造函數,當增加數據時,數據實際容量超過16*0.75=12時,HashMap就擴容,擴容帶來一系列的運算,新建一個是原來容量2倍的數組,對原有元素全部重新哈希,如果你的數據有幾千幾萬個,而用默認的HashMap構造函數,那結果是非常悲劇的,因為HashMap不斷擴容,不斷哈希,


2.Hashtalbe與ConcurrentHashMap區別

相同點:Hashtable和ConcurrentHashMap都是線程安全的,可以在多線程環境中運行;key和value都不能為null

區別:兩者主要是性能上的差異,Hashtable的所有操作都會鎖住整個對象,雖然能夠保證線程安全,但是性能較差;ConcurrentHashMap內部使用Segment數組,其實和Entry類似,它不是加synchronized關鍵字來保證同步,而是基於lock操作(例如put()方法中調用了ReentrantLock類的lock()方法),這樣能避免鎖住整個對象。事實上ConcurrentHashMap可以滿足concurrentLevel個線程並發無阻塞的操作集合對象。

ConcurrentHashMap基於concurrentLevel劃分出了多個Segment來對key-value進行存儲,從而避免每次鎖定整個數組,在默認的情況下,允許16個線程並發無阻塞的操作集合對象,盡可能地減少並發時的阻塞現象。


下面引用一段話來說明ConcurrentHashMap和Hashtable:

Hashtable的任何操作都會把整個表鎖住,是阻塞的。好處是總能獲取最實時的更新,比如說線程A調用putAll寫入大量數據,期間線程B調用get,線程B就會被阻塞,直到線程A完成putAll,因此線程B肯定能獲取到線程A寫入的完整數據。壞處是所有調用都要排隊,效率較低。
ConcurrentHashMap 是設計為非阻塞的。在更新時會局部鎖住某部分數據,但不會把整個表都鎖住。同步讀取操作則是完全非阻塞的。好處是在保證合理的同步前提下,效率很高。壞處 是嚴格來說讀取操作不能保證反映最近的更新。例如線程A調用putAll寫入大量數據,期間線程B調用get,則只能get到目前為止已經順利插入的部分 數據。此外,使用默認構造器創建的ConcurrentHashMap比較占內存,如果程序需要創建巨量ConcurrentHashMap,應該在構造時指定concurrencyLevel


更詳細參考資料:

http://pi88dian88.iteye.com/blog/2008160

http://blog.csdn.net/zhangerqing/article/details/8193118


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved