根据 Java 文档,对象的哈希代码计算如下:String
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
使用算术,其中 是
字符串的第 i个字符,是字符串的
长度,表示幂。int
s[i]
n
^
为什么用31作为乘数?
我知道乘数应该是一个相对较大的质数。那么为什么不是 29、37 甚至 97 呢?
根据Joshua Bloch的Effective Java(一本推荐不够的书,由于不断提到stackoverflow,我买了这本书):
选择值 31 是因为它是一个奇数素数。如果是偶数并且乘法溢出,则信息将丢失,因为乘以 2 等同于移位。使用素数的优点不太明显,但它是传统的。31 的一个很好的属性是乘法可以用移位和减法代替以获得更好的性能:。新式 VM 会自动执行此类优化。
31 * i == (i << 5) - i
(摘自第 3 章第 9 项:覆盖等于时始终覆盖哈希代码,第 48 页)
Goodrich 和 Tamassia 根据超过 50,000 个英语单词(由 Unix 的两个变体中提供的单词列表的联合组成)计算出,使用常量 31、33、37、39 和 41 在每种情况下将产生少于 7 次碰撞。这可能是许多Java实现选择此类常量的原因。
请参阅Java中的数据结构和算法的第9.2节哈希表(第522页)。
在(大多数)旧处理器上,乘以 31 可能相对便宜。例如,在ARM上,它只有一个指令:
RSB r1, r0, r0, ASL #5 ; r1 := - r0 + (r0<<5)
大多数其他处理器需要单独的移位和减法指令。但是,如果您的乘数很慢,这仍然是一场胜利。现代处理器往往具有快速乘法器,因此只要 32 在正确的一侧,它就不会有太大区别。
它不是一个很好的哈希算法,但它足够好,比 1.0 代码更好(比 1.0 规范好得多!
模板简介:该模板名称为【对象的哈希代码:字符串的第 i个字符,是字符串的长度】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【Java】栏目查找您需要的精美模板。