簡體   English   中英

我可以使用GetHashCode()進行所有字符串比較嗎?

[英]Can i use GetHashCode() for all string compares?

我想基於要搜索的對象和一些搜索設置來緩存一些搜索結果。

但是:這會創建相當長的緩存鍵,我想我會為它創建一個快捷方式,我想我會使用GetHashCode()

所以我想知道, GetHashCode()總是生成一個不同的數字,即使我有很長的字符串或只有這個不同:'ä'而不是'a'

我嘗試了一些字符串, 似乎答案是肯定的,但不了解GetHashCode()行為並沒有給我真正的感覺,我是對的。

而且因為當你沒有准備好時(客戶端正在查看錯誤搜索的緩存結果),它會突然出現,我想確定...

編輯:如果MD5可以工作,我可以改變我的代碼不使用GetHashCode ofcourse,目標是得到一個短的(呃)字符串比原來(> 1000字符)

你不能指望GetHashCode()是唯一的。

http://kenneththorman.blogspot.com/2010/09/c-net-equals-and-gethashcode.html上有一篇很好的文章可以調查碰撞的可能性。 調查結果是“GetHashCode()調用不同字符串返回相同哈希碼的最小次數是在565次迭代之后,獲得哈希碼沖突之前的最大迭代次數是296390次迭代。”

因此,您可以了解GetHashCode實現的合同,以下是Object.GetHashCode() MSDN文檔的摘錄:

哈希函數必須具有以下屬性:

  • 如果兩個對象比較相等,則每個對象的GetHashCode方法必須返回相同的值。 但是,如果兩個對象的比較不相等,則兩個對象的GetHashCode方法不必返回不同的值。

  • 只要沒有對對象狀態的修改來確定對象的Equals方法的返回值,對象的GetHashCode方法必須始終返回相同的哈希代碼。 請注意,這僅適用於當前應用程序的執行,並且如果再次運行應用程序,則可以返回不同的哈希代碼。

  • 為獲得最佳性能,哈希函數必須為所有輸入生成隨機分布。

C#編譯器團隊的Eric Lippert在他的博客http://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/上解釋了GetHashCode實現規則的基本原理。

邏輯上, GetHashCode 不能是唯一的,因為只有2 ^ 32個int和無限數量的字符串(參見鴿子孔原理)。


正如@Henk在評論中指出的那樣,即使存在無限數量的字符串,也存在有限數量的System.String 然而,鴿子洞原則仍然存在,因為后者比int.MaxValue

如果存儲每個字符串的哈希碼以及字符串本身,則可以將字符串的哈希碼作為“第一步”來比較它們的相等性。 如果兩個字符串具有不同的哈希碼,則它們不相等,並且不需要做任何其他事情。 如果希望比較具有相同長度且“幾乎”但不完全相等的許多字符串對,則在檢查內容之前檢查哈希碼可能是有用的性能優化。 請注意,如果沒有緩存的哈希碼,這種“優化”就不值得,因為計算兩個字符串的哈希碼幾乎肯定比比較它們要慢 但是,如果為了某些其他目的而必須計算和緩存哈希碼,則檢查哈希碼作為比較字符串的第一步可能是有用的。

使用GetHashCode()時總是冒着沖突的風險,因為您在有限數量的空間Int32中運行,並且哈希算法無法在此空間內完美分布這一事實也會加劇這種情況。

如果查看HashTable或Dictionary的實現,您將看到GetHashCode用於將密鑰分配到存儲桶中以減少所需的比較次數,但是,如果同一存儲桶中有多個項目,則仍需要進行相等比較。

不,GetHasCode只提供哈希碼。 會有碰撞。 具有不同的散列意味着字符串不同,但具有相同的散列並不意味着字符串是相同的。

閱讀Eric Lippert的這些guidlelines以正確使用GetHashCode ,他們非常指導。

如果你想比較字符串,就這樣做吧! stringA == stringB工作正常。 如果要確保字符串在大型集合中是唯一的,請使用哈希代碼的強大功能,使用HashSet<string>

暫無
暫無

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

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