Java之 Hashtable

Hashtable是Java中鍵值對數據結構的實現。您可使用「鍵」存儲和檢索「值」,它是存儲值的標識符顯然「關鍵」應該是獨一無二的。java

java.util.Hashtable擴展Dictionary並實現Map。具備非空值的對象能夠用做鍵或值。Hashtable的密鑰必須實現hashcode()和equals()方法。在這篇文章的最後,你會發現這個條件背後的緣由。哈希表數據結構

一般,使用空構造函數 Hashtable()建立Java中的Hashtable。這是一個糟糕的決定,並且常常重複的錯誤。Hashtable有兩個其餘構造函數jvm

Hashtable(int initialCapacity)int initialCapacity 

函數

Hashtable(int initialCapacity,float loadFactor)int initialCapacity float loadFactor 

初始容量是在Hashtable實例化時建立的桶數。桶的邏輯空間存儲的哈希表。性能

哈希和哈希表

在查看java的Hashtable以前,你應該明白通常的哈希。假設v是要存儲的值,k是用於存儲/檢索的密鑰,則h是在表的h(k)處存儲v的哈希函數。要獲取值計算h(k),以便您能夠直接獲取v的位置。所以,在鍵值對錶中,您不須要順序掃描鍵以識別值。

h(k)是散列函數,它用於找到存儲對應值的位置v。h(k)不能計算到不肯定空間。分配給Hashtable的存儲在程序中受到限制。所以,散列函數h(k)應該返回該分配頻譜(邏輯地址空間內的一個數字spa

在Java中進行散列

Java的散列使用從鍵和值對象使用hashCode()方法進行計算。如下是來自Hashtable的核心代碼,其中計算了hashCode'h'。你能夠看到key和value的hashCode()方法被調用。code

h += e.key.hashCode() ^ e.value.hashCode();
  += e.key.hashCode() ^ e.value.hashCode();

 

 

最好在您的自定義對象中使用hashCode()方法。String具備本身的hashCode方法,它計算hashcode值以下:對象

 
s[0]*31^(n-1) 
    + s[1]*31^(n-2) 
    + ... 
    + s[n-1][0]*31^(n-1) + s[1]*31^(n-2) 
  + ... + s[n-1]

 

 

若是沒有hashCode()方法,那麼它是從Object類派生的。如下是來自Object類的hashCode()方法的javadoc註釋blog

返回對象的哈希碼值。支持這種方法是爲了哈希表的好處,如java.util.Hashtable提供的那些。內存

若是要編寫一個自定義的hashCode(),那麼請遵循如下合同:

hashCode的通常契約是:不管什麼時候在執行Java應用程序時屢次在同一對象上調用該對象,hashCode方法必須始終返回相同的整數,前提是在對象上的equals比較中沒有使用任何信息被修改。

如下是提升Hashtable的性能。

若是兩個對象根據equals(Object)方法相等,那麼在兩個對象中的每一個對象上調用hashCode方法必須產生相同的整數結果。

hashCode()經過使用對象的內部地址來保證不一樣的整數。

碰撞在Hashtable

當咱們嘗試在分配的地址範圍限制範圍內限制散列函數的輸出時,有可能發生衝突。對於兩個不一樣的鍵k1和k2,若是咱們有h(k1)= h(k2),那麼這就是哈希表中的碰撞。這是什麼意思,咱們的散列函數指示咱們在同一位置存儲兩個不一樣的值(鍵也不一樣)。

當碰撞時,有多種方法能夠解決它。命名幾個哈希表衝突解決技術,「單獨連接」,「開放尋址」,「羅賓蓋哈希」,「布穀鳥哈希」等。Java的哈希表使用「分離連接」來在Hashtable中進行衝突解決。

在Java的Hashtable中的碰撞解決方案

Java使用單獨的連接進行衝突解決。回想一下,Hashtable將元素存儲在存儲桶中。在單獨連接中,每一個桶將存儲對鏈表的引用。如今假設你已經存儲了一個元素在桶1中。這意味着,在第1桶中,您將有一個鏈表的引用,在該鏈表中,您將有兩個單元格。在這兩個單元格中,您將具備鍵及其相應的值。哈希表碰撞

爲何要存儲密鑰?由於當有衝突時,即當兩個鍵產生相同的哈希碼並指向相同的存儲桶(假設存儲桶1)時,您也要將第二個元素存儲在同一個存儲桶中。將此第二個元素添加到已建立的連接列表做爲相鄰元素。

如今,當您檢索到一個值時,它將計算哈希碼並將其引導到具備兩個元素的存儲桶。您能夠順序掃描這兩個元素,並使用它們的equals()方法比較鍵。當關鍵數學你獲得相應的值。但願你有理由背後的條件,你的對象必須有hashCode()和equals()方法。

Java在Hashtable中有一個私有靜態類Entry。它是一個列表的實現,你能夠看到,它存儲的關鍵和價值。

哈希表演

要從您的Java Hashtable得到更好的性能,您須要
使用initialCapacity和loadFactor參數
2)
在實例化Hashtable時明智地使用它們

initialCapacitiy是在Hashtable實例化時建立的桶數。桶的數量和碰撞的機率是相反的。若是您須要更多的桶數,則碰撞的可能性較小。

例如,若是要存儲10個元素,而且若是要將initialCapacity設置爲100,那麼您將擁有100個桶。您將計算hashCoe()只有10次,頻譜爲100個桶。碰撞的可能性很是少。

可是,若是要將Hashtable的initialCapacity提供爲10,則碰撞的可能性很是大。loadFactor決定什麼時候自動增長Hashtable的大小。initialCapacity的默認大小爲11,loadFactor爲.75若是Hashtable的大小爲3/4,則Hashtable的大小將增長。

Java Hashtable中的新容量計算以下:

	int newCapacity = oldCapacity * 2 + 1;int newCapacity = oldCapacity * 2 + 1 ;

若是您提供較小的容量和加載因子,而且一般會執行rehash(),這會致使性能問題。所以,爲了在Java中實現Hashtable的高效性能,在實例化時,將initialCapacity做爲您須要的25%,loadFactor爲0.75。

相關文章
相關標籤/搜索