jdk6的源碼:
以字元串"123"為例:
字元'1'的ascii碼是49
hashcode = (49*31 + 50)*31 + 51
或者這樣看:
hashcode=('1' * 31 + '2' ) * 31 + '3'
可見實際可以看作是一種權重的算法,在前面的字元的權重大。
這樣有個明顯的好處,就是字首相同的字元串的hash值都落在鄰近的區間。
好處有兩點:
1.可以節省記憶體,因為hash值在相鄰,這樣hash的數組可以比較小。比如當用hashmap,以string為key時。
2.hash值相鄰,如果存放在容器,比好hashset,hashmap中時,實際存放的記憶體的位置也相鄰,則存取的效率也高。(程式局部性原理)
以31為倍數,原因了31的二進制全是1,則可以有效地離散資料。
最後看下,兩個字元串,由eclipse生成的代碼是如何計算hash值的:
可見,還是以31為倍數, hashcode = firstname.hashcode() * 31 + lastname.hashcode() 。
btw:java的字元串的hash做了緩存,第一次才會真正算,以後都是取緩存值。
eclipse生成的equals函數品質也很高,各種情況都考慮到了。
總結:字元串hash函數,不僅要減少沖突,而且要注意相同字首的字元串生成的hash值要相鄰。