為什么Java String哈希函數(shù)乘數(shù)為31?
哈嘍,大家好,我是了不起。
今天給大家介紹一個(gè)底層數(shù)字問題——為什么Java String哈希函數(shù)乘數(shù)為31?
1、源碼重現(xiàn)
在這個(gè)實(shí)現(xiàn)中,31 被用作乘數(shù)。那么,為什么選擇 31 作為乘數(shù)呢?
2、降低哈希沖突
31 是一個(gè)質(zhì)數(shù),相信大家學(xué)過數(shù)學(xué)的,質(zhì)數(shù)是這樣定義的:
指在大于1的自然數(shù)中,除了1和它本身以外沒有任何正因數(shù)的自然數(shù)。
在哈希函數(shù)中,使用質(zhì)數(shù)作為乘數(shù)可以提高哈希值的分布均勻性。如果使用非質(zhì)數(shù)作為乘數(shù),那么哈希值的分布可能會(huì)出現(xiàn)偏斜。
例如,如果使用 10 作為乘數(shù),那么所有以 5 為尾數(shù)的字符串的哈希值將是相同的。這會(huì)導(dǎo)致哈希沖突的可能性增加。
3、提高哈希計(jì)算速度
在 Java 中,int 類型的變量占用 32 位。
31 是一個(gè)奇數(shù),因此 31 * i 的結(jié)果可以只使用 31 位來表示。這意味著在計(jì)算哈希值時(shí),可以使用位運(yùn)算來代替乘法運(yùn)算。
位運(yùn)算比乘法運(yùn)算要快得多。
因此,使用 31 作為乘數(shù)可以提高哈希計(jì)算速度。
4、31是一個(gè)良好的折中方案
在實(shí)際應(yīng)用中,使用 31 作為乘數(shù)可以提供良好的哈希值分布和計(jì)算速度。當(dāng)然,也可以使用其他質(zhì)數(shù)作為乘數(shù)。例如,37 和 43 也是不錯(cuò)的選擇。
但是,31 是一個(gè)相對(duì)較小的質(zhì)數(shù),因此它在計(jì)算速度方面具有優(yōu)勢(shì)。此外,31 也是一個(gè)常用的質(zhì)數(shù),因此在許多其他哈希函數(shù)中也得到了使用。
當(dāng)然,31 并不是一個(gè)完美的乘數(shù)。在某些情況下,使用其他質(zhì)數(shù)可能會(huì)更好。但是,對(duì)于大多數(shù)應(yīng)用程序來說,31 都是一個(gè)不錯(cuò)的選擇。