2014-01-13 58 views
4

正如紀錄片中所說的,「這段代碼濫用loadFactor字段來執行double-duty作爲正在進行中的hashCode標誌,所以沒有惡化空間性能。負載因子表明散列碼計算正在進行中。「 如何理解這一段?如何理解JDK的源代碼中的java.util.Hashtable的hashCode函數

public synchronized int hashCode() { 
    /* 
    * This code detects the recursion caused by computing the hash code 
    * of a self-referential hash table and prevents the stack overflow 
    * that would otherwise result. This allows certain 1.1-era 
    * applets with self-referential hash tables to work. This code 
    * abuses the loadFactor field to do double-duty as a hashCode 
    * in progress flag, so as not to worsen the space performance. 
    * A negative load factor indicates that hash code computation is 
    * in progress. 
    */ 
    int h = 0; 
    if (count == 0 || loadFactor < 0) 
     return h; // Returns zero 

    loadFactor = -loadFactor; // Mark hashCode computation in progress 
    Entry[] tab = table; 
    for (int i = 0; i < tab.length; i++) 
     for (Entry e = tab[i]; e != null; e = e.next) 
      h += e.key.hashCode()^e.value.hashCode(); 
    loadFactor = -loadFactor; // Mark hashCode computation complete 

return h; 
+1

您試圖解決什麼問題? –

+0

Thranks for your help.I只讀源代碼,無法理解爲什麼作者使用loadFactor作爲hashcode的計算進度中的一個標誌。設置此標誌的含義是什麼?此函數是自身同步的,因此它的線程安全,不是嗎? –

+0

這不是一個線程問題。例如,如果例如循環將發生。 'e.value'指向與'this'相同的散列表。即使只有一個線程,也會發生這種情況,正如@Jasper所指出的那樣,如果沒有檢測到它會導致堆棧溢出。 –

回答

2

使用客座率爲正在進行的檢查的目的是爲了確保代碼不會陷入無限循環,如果有引用的循環鏈回哈希表本身。例如,想象一個類型爲Hashtable<String,Hashtable>的散列表,即從字符串到其他散列表的映射。然後,表中的條目可能包含對同一散列表本身的引用;或者,它可能指向另一個相同類型的哈希表,然後再指向同一個表。由於散列碼遞歸計算鍵和值的哈希碼,然後將它們組合以產生最終的哈希碼,如果它未檢測到循環引用(圖中的循環),它將陷入無限循環。

當代碼遇到循環引用時,它會注意到這一點,因爲加載因子將爲負值,表示已經遇到哈希表。在這種情況下,它將通過返回0來打破循環,而不是進一步遞歸。

我在XEmacs上做了很多工作,在它的Lisp解釋器中有類似的哈希代碼。它使用了一個不同的技巧:它有一個遞歸深度值,該值被傳遞到函數的等價物中,並在每次函數遞歸到另一個對象時遞增。如果深度超過一定數量,則拒絕進一步遞減。這比Java的技巧更脆弱,但在Java中是不可能的,因爲hashCode函數的簽名是固定的,並且沒有遞歸深度參數。

+0

非常感謝!您的回答對我來說真的很有用。^ _^ –

+0

不客氣! –