簡體   English   中英

Java String上散列碼溢出的后果

[英]Consequences of hashcode overflow on Java String

我最近在這里閱讀了一些關於Java String類'哈希碼的內容,但是我無法找到這些信息:當字符串的長度大於32時會發生什么(我知道會發生溢出,但是作為哈希鍵, 怎么了)? 例如,我需要散列長度在20到120個字符之間的字符串,以將它們用作散列鍵。 我是否需要使用BigInteger實現自己的算法?

另外,既然我可能有30k到80k之間的字符串,也許更多,那么通常的String hashcode是否足夠無沖突?

(我知道會發生溢出,但作為哈希鍵,會發生什么)?

在Java中,原始類型的算術溢出和下溢不會引發運行時錯誤或異常。 結果溢出的部分就完全丟失了。

如果程序員不知道此屬性,則會導致邏輯錯誤或其他困難,但這是JVM的指定行為。

在計算哈希碼時,您不必擔心int類型的溢出或下溢。 溢出的位簡直就丟失了。

這不會影響計算的哈希值的正確性或其分配給哈希桶的能力。

另外,既然我可能有30k到80k之間的字符串,也許更多,那么通常的String hashcode是否足夠無沖突?

一些可以方便記住的事情:

  • Java字符串是不可變的。 因此,String實例的哈希值只計算一次。 之后,結果緩存在實例中,以便后續調用hashCode()不會導致重復計算。 這是有效的,因為字符串是不可變的,重新計算的值每次都是相同的。

  • 實際上應該根據實例中的所有有意義的信息來計算哈希碼。 這意味着如果你的String包含20k的信息,那么哈希碼應該從它的所有20k中計算出來(但參見上文)。 當然,有性能影響,所以你應該相應地設計你的程序。

  • 碰撞'free'-ness與hashCode()實現的質量有很大關系,而與你的字符串大小關系不大。 用於生成哈希碼的算法應該能夠產生良好的分布。 什么是“好的散列函數”並不是精確已知的,而是數學理論家的主題。 幸運的是,定義一個“足夠好”的哈希函數並不難,即使它可能不是“最先進的”(參見Effective Java,2nd ed .; J. Bloch)。

你誤解了hashCode()作用。 它計算一個32位數,對於不同的值應該是不同的,但不保證是這樣。 怎么可能,那么哈希可能有超過2 ^ 32個不同的值。

對於String ,hashCode與字符串長度無關。 任何hashCode都是任何字符串的有效hashCode,只要你總是為同一個String獲得相同的 hashCode,即對同一個字符序列多次調用hashCode() 必須返回相同的值。

作為示例,這里是字符串的一些哈希碼。

0x00000000 = "".hashCode()
0x00000061 = "a".hashCode()
0x00000041 = "A".hashCode()
0x042628b2 = "Hello".hashCode()
0x6f8f80f1 = "Goodbye".hashCode()
0xdbacdd53 = "The quick brown fox jumps over the lazy dog".hashCode()
0x99eecd2e = "The quick brown fox jumps over the lazy dog!".hashCode()

請注意,最后兩個是一個非常長(> 32)的字符串。

字符串沒有溢出。 字符串可以與進程的內存一樣長。 任何String的hashCode都是32位整數。 碰撞頻率不應與String的長度相關。 你不需要重新實現它。

暫無
暫無

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

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