簡體   English   中英

什么哈希算法.net使用? 小丑怎么樣?

[英]What hash algorithm does .net utilise? What about java?

關於HashTable(以及后來的衍生產品),有誰知道什么是哈希算法.net和Java?

列表和詞典都是Hashtable的直接后代嗎?

哈希函數沒有內置到哈希表中; 哈希表調用密鑰對象上的方法來計算哈希值。 因此,散列函數根據密鑰對象的類型而變化。

在Java中, List不是哈希表(也就是說,它不擴展Map接口)。 可以在內部實現帶有哈希表的List (稀疏列表,其中列表索引是哈希表的關鍵),但是這樣的實現不是標准Java庫的一部分。

我對.NET一無所知,但我會嘗試代表Java。

在Java中,哈希代碼最終是給定對象的hashCode()函數返回的代碼和HashMap / ConcurrentHashMap類中的輔助哈希函數的組合(有趣的是,兩者使用不同的函數)。 請注意,Hashtable和Dictionary(HashMap和AbstractMap的前身)是過時的類。 列表實際上只是“別的東西”。

例如,String類通過將當前代碼重復乘以31並添加下一個字符來構造哈希代碼。 有關更多信息,請參閱有關String哈希函數如何工作的文章。 數字通常使用“自己”作為哈希碼; 其他類,例如Rectangle,具有字段組合,通常使用String技術的組合乘以小素數並加入,但添加各種字段值。 (選擇一個素數意味着你不可能在某些值和哈希碼寬度之間得到“偶然的交互”,因為它們不會被任何東西分開。)

由於散列表大小 - 即它具有的“桶”的數量 - 是2的冪,因此基本上通過砍掉最高位直到散列碼在范圍內來從散列碼導出桶號。 輔助散列函數防止散列函數,其中所有或大部分隨機性位於那些頂部位,通過“擴展位”,使得一些隨機性最終位於底部位並且不會被丟棄。 如果沒有這種混合,String哈希代碼實際上可以很好地工作,但是用戶創建的哈希代碼可能效果不是很好。 請注意,如果兩個不同的哈希碼解析為相同的桶號,則Java的HashMap實現使用“鏈接”技術 - 即它們在每個桶中創建條目的鏈接列表。 因此,哈希碼具有良好的隨機性非常重要,因此項目不會聚集到特定范圍的桶中。 (但是,即使具有完美的散列函數,您仍然可以通過平均法則預期會發生一些鏈接。)

散列碼實現應該不是一個謎。 您可以查看您選擇的任何類的hashCode()源代碼。

在我自己尋找相同的答案時,我在.net的參考源@ http://referencesource.microsoft.com中找到了這個。

     /*
      Implementation Notes:
      The generic Dictionary was copied from Hashtable's source - any bug 
      fixes here probably need to be made to the generic Dictionary as well.
      This Hashtable uses double hashing.  There are hashsize buckets in the 
      table, and each bucket can contain 0 or 1 element.  We a bit to mark
      whether there's been a collision when we inserted multiple elements
      (ie, an inserted item was hashed at least a second time and we probed 
      this bucket, but it was already in use).  Using the collision bit, we
      can terminate lookups & removes for elements that aren't in the hash
      table more quickly.  We steal the most significant bit from the hash code
      to store the collision bit.

      Our hash function is of the following form:

      h(key, n) = h1(key) + n*h2(key)

      where n is the number of times we've hit a collided bucket and rehashed
      (on this particular lookup).  Here are our hash functions:

      h1(key) = GetHash(key);  // default implementation calls key.GetHashCode();
      h2(key) = 1 + (((h1(key) >> 5) + 1) % (hashsize - 1));

      The h1 can return any number.  h2 must return a number between 1 and
      hashsize - 1 that is relatively prime to hashsize (not a problem if 
      hashsize is prime).  (Knuth's Art of Computer Programming, Vol. 3, p. 528-9)
      If this is true, then we are guaranteed to visit every bucket in exactly
      hashsize probes, since the least common multiple of hashsize and h2(key)
      will be hashsize * h2(key).  (This is the first number where adding h2 to
      h1 mod hashsize will be 0 and we will search the same bucket twice).

      We previously used a different h2(key, n) that was not constant.  That is a 
      horrifically bad idea, unless you can prove that series will never produce
      any identical numbers that overlap when you mod them by hashsize, for all
      subranges from i to i+hashsize, for all i.  It's not worth investigating,
      since there was no clear benefit from using that hash function, and it was
      broken.

      For efficiency reasons, we've implemented this by storing h1 and h2 in a 
      temporary, and setting a variable called seed equal to h1.  We do a probe,
      and if we collided, we simply add h2 to seed each time through the loop.

      A good test for h2() is to subclass Hashtable, provide your own implementation
      of GetHash() that returns a constant, then add many items to the hash table.
      Make sure Count equals the number of items you inserted.

      Note that when we remove an item from the hash table, we set the key
      equal to buckets, if there was a collision in this bucket.  Otherwise
      we'd either wipe out the collision bit, or we'd still have an item in
      the hash table.

       -- 
    */

HASHING算法是用於確定HashTable中項目的哈希碼的算法。

HASHTABLE算法(我認為是這個人所問的)是HashTable在給定哈希碼時用來組織其元素的算法。

Java碰巧使用鏈式哈希表算法。

在.NET中任何聲稱是HashTable或類似東西的東西都沒有實現它自己的散列算法:它們總是調用object-being-hashed的GetHashCode()方法。

關於此方法執行或應該執行的操作存在很多混淆,尤其是涉及覆蓋基礎Object實現的用戶定義或其他自定義類時。

對於.NET,您可以使用Reflector查看各種算法。 泛型和非泛型散列表有一個不同的,當然每個類定義自己的散列碼公式。

.NET Dictionary<T>類使用IEqualityComparer<T>來計算密鑰的哈希碼,並執行密鑰之間的比較以進行哈希查找。 如果你不提供IEqualityComparer<T>構造時Dictionary<T>實例(這是一個可選參數構造函數),它會創建一個默認了一個給你,它使用object.GetHashCodeobject.Equals默認方法。

至於標准的GetHashCode實現如何工作,我不確定它是否有記錄。 對於特定類型,您可以在Reflector中讀取方法的源代碼,或嘗試檢查Rotor源代碼以查看它是否存在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM