[英]Hashing function in Hashtable vs. HashMap?
我知道Hashtable和HashMap之間的區別。 但是,這兩個類似乎都在使用哈希函數來完成工作。 Hashtable中使用的哈希函數和HashMap中使用的哈希函數之間有區別嗎?
特別是,他們使用的散列算法有區別嗎? 在這兩個類中使用哈希的公式是什么?
換句話說,計算索引(哈希值)的方式是不同的?
特別是,他們使用的散列算法有區別嗎? 在這兩個類中使用哈希的公式是什么?
將對象用作哈希表鍵時使用的主哈希函數是對象的hashCode()
方法。 實現一個像樣的哈希函數是關鍵類。
Hashtable
和HashMap
類獲取密鑰的哈希碼值並將其轉換為主哈希表數組鏈中的索引。 但是,在Hashtable
和HashMap
之間發生這種情況有所不同。
對於Hashtable
(Java 8),代碼是這樣的:
hash = key.hashCode(); index = (hash & 0x7FFFFFFF) % tab.length;
對於HashMap
(Java 8),代碼是(有效地):
// (I have restructured the code for ease of comparison.) int h; hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); index = (tab.length - 1) & hash;
如您所見, HashMap
正在加擾密鑰哈希碼函數返回的哈希碼值。 這在源代碼中解釋如下:
[此方法]計算key.hashCode()並將更高位的散列擴展(XOR)降低。 因為該表使用2次冪掩蔽,所以僅在當前掩碼之上的位中變化的散列組將始終發生沖突。 (在已知的例子中是一組Float鍵,在小表中保存連續的整數。)因此我們應用一個向下傳播高位比特影響的變換。 速度,效用和比特擴展質量之間存在權衡。 因為許多常見的哈希集合已經合理分布(因此不會受益於傳播),並且因為我們使用樹來處理容器中的大量沖突,所以我們只是以最便宜的方式對一些移位的位進行異或,以減少系統損失,以及由於表格邊界而包含最高位的影響,否則這些位將永遠不會用於索引計算。
筆記:
&
vs %
差異是因為在Hashtable
中哈希數組大小是素數,但在HashMap
(Java 8)中,大小是2的冪。
在Java 8 HashMap
,如果密鑰類實現Comparable
,則實現將把長哈希鏈轉換為二叉樹。
HashMap
處理null
鍵,但Hashtable
不處理。
但是,如果您的密鑰類具有設計糟糕/實現的hashCode()
方法......或者有人故意設計哈希沖突,那么HashMap
所有這些額外的復雜性才會發揮作用。
換句話說,如果你的關鍵類設計得很好,那么差異就不重要了 。
java.util.Hashtable<K,V>
與java.util.Vector<T>
類似。 它是在開發早期就添加到SDK中的類,已被HashMap<K,V>
ArrayList<T>
取代(如ArrayList<T>
取代Vector<T>
)。
所以你根本不應該使用它,除非你需要默認使用Hashtable
的所有操作的隱式同步,但是你可以為此目的使用Collections.synchronizedMap
或者ConcurrentHashMap<K,V>
。
正如Javadoc所述:
從Java 2平台v1.2開始,這個類被改進以實現
Map
接口,使其成為Java Collections Framework的成員。 與新的集合實現不同,Hashtable
是同步的。 如果不需要線程安全實現, 建議使用HashMap
代替Hashtable
。 如果需要線程安全的高度並發實現,那么建議使用ConcurrentHashMap
代替Hashtable
。
兩個類的散列應該是相同的,因為它們都使用int Object::hashCode
來實現它們的目的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.