本文翻译自:Why does Java's hashCode() in String use 31 as a multiplier?

Per the Java documentation, the hash code for a String object is computed as: 根据Java文档, String对象的哈希码计算如下:

 s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] 

using int arithmetic, where s[i] is the i th character of the string, n is the length of the string, and ^ indicates exponentiation. 使用int算术,其中s[i]是字符串的第i个字符, n是字符串的长度, ^表示取幂。

Why is 31 used as a multiplier? 为什么31用作乘数?

I understand that the multiplier should be a relatively large prime number. 我知道乘数应该是一个相对较大的素数。 So why not 29, or 37, or even 97? 那么为什么不是29岁,37岁,甚至97岁?


#1楼

参考:https://stackoom.com/question/1FrU/为什么String中的Java-hashCode-使用-作为乘数


#2楼

Bloch doesn't quite go into this, but the rationale I've always heard/believed is that this is basic algebra. 布洛赫并没有深入研究这个问题,但我一直听到/相信的理由是这是基本的代数。 Hashes boil down to multiplication and modulus operations, which means that you never want to use numbers with common factors if you can help it. 哈希值可归结为乘法和模数运算,这意味着如果可以提供帮助,您永远不会想要使用具有公共因子的数字。 In other words, relatively prime numbers provide an even distribution of answers. 换句话说,相对素数提供了均匀的答案分布。

The numbers that make up using a hash are typically: 使用哈希构成的数字通常是:

  • modulus of the data type you put it into (2^32 or 2^64) 你把它放入的数据类型的模数(2 ^ 32或2 ^ 64)
  • modulus of the bucket count in your hashtable (varies. In java used to be prime, now 2^n) 哈希表中的桶数的模数(各不相同。在java以前是素数,现在是2 ^ n)
  • multiply or shift by a magic number in your mixing function 在混音函数中乘以幻数或乘以幻数
  • The input value 输入值

You really only get to control a couple of these values, so a little extra care is due. 你真的只能控制这些价值,所以需要额外注意。


#3楼

我不确定,但我猜他们测试了一些素数样本,并发现31在一些可能的字符串样本中得到了最好的分布。


#4楼

On (mostly) old processors, multiplying by 31 can be relatively cheap. 在(大多数)旧处理器上,乘以31可能相对便宜。 On an ARM, for instance, it is only one instruction: 例如,在ARM上,它只有一条指令:

RSB       r1, r0, r0, ASL #5    ; r1 := - r0 + (r0<<5)

Most other processors would require a separate shift and subtract instruction. 大多数其他处理器需要单独的移位和减法指令。 However, if your multiplier is slow this is still a win. 但是,如果你的乘数很慢,这仍然是一个胜利。 Modern processors tend to have fast multipliers so it doesn't make much difference, so long as 32 goes on the correct side. 现代处理器往往具有快速乘法器,因此它没有太大的区别,只要32在正确的一侧。

It's not a great hash algorithm, but it's good enough and better than the 1.0 code (and very much better than the 1.0 spec!). 它不是一个很好的哈希算法,但它足够好并且比1.0代码更好(并且比1.0规范好得多!)。


#5楼

According to Joshua Bloch's Effective Java (a book that can't be recommended enough, and which I bought thanks to continual mentions on stackoverflow): 根据Joshua Bloch的Effective Java (一本不能推荐的书,以及我在stackoverflow上不断提及而购买的书):

The value 31 was chosen because it is an odd prime. 选择值31是因为它是奇数素数。 If it were even and the multiplication overflowed, information would be lost, as multiplication by 2 is equivalent to shifting. 如果它是偶数并且乘法溢出,则信息将丢失,因为乘以2相当于移位。 The advantage of using a prime is less clear, but it is traditional. 使用素数的优势不太明显,但它是传统的。 A nice property of 31 is that the multiplication can be replaced by a shift and a subtraction for better performance: 31 * i == (i << 5) - i . 31的一个很好的属性是乘法可以用移位和减法代替以获得更好的性能: 31 * i == (i << 5) - i Modern VMs do this sort of optimization automatically. 现代VM自动执行此类优化。

(from Chapter 3, Item 9: Always override hashcode when you override equals, page 48) (来自第3章,第9项:覆盖等于时始终覆盖哈希码,第48页)


#6楼

As Goodrich and Tamassia point out, If you take over 50,000 English words (formed as the union of the word lists provided in two variants of Unix), using the constants 31, 33, 37, 39, and 41 will produce less than 7 collisions in each case. 正如古德里奇和塔玛西亚指出的那样,如果你接受超过50,000个英语单词(形成为两个Unix变体中提供的单词列表的联合),使用常数31,33,37,39和41将产生少于7个冲突在每种情况下。 Knowing this, it should come as no surprise that many Java implementations choose one of these constants. 知道这一点,许多Java实现选择其中一个常量应该不足为奇。

Coincidentally, I was in the middle of reading the section "polynomial hash codes" when I saw this question. 巧合的是,当我看到这个问题时,我正在阅读“多项式哈希码”部分。

EDIT: here is link to the ~10mb PDF book i'm referring to above. 编辑:这里是我上面提到的~10mb PDF书的链接。 See section 10.2 Hash Tables (page 413) of Data Structures and Algorithms in Java 请参见Java中的数据结构和算法的第10.2节哈希表(第413页)

为什么String中的Java hashCode()使用31作为乘数?相关推荐

  1. Java中string中hashcode_为什么String中的Java hashCode()使用31作为乘数?

    从JDK-4045622开始,Joshua Bloch描述了选择特定(新) String.hashCode() 实施的原因 下表总结了上述各种哈希函数的性能,对于三个数据集:1)Merriam-Web ...

  2. tsql语句中的t是什么_TSQL中的Java HashCode

    tsql语句中的t是什么 The Java HashCode method is used to determine uniqueness or similarity of strings. Whil ...

  3. java继承中的 equals + hashCode+toString

    [0]README 0.1)本文转自 core java volume 1, 旨在理清 equals + hashCode方法: 0.2) 特别说明: 在java中, 只有基本类型不是对象, 例如,数 ...

  4. 有关java中equals()与hashCode()的探讨

    参考文章:从一道面试题彻底搞懂hashCode与equals的作用与区别及应当注意的细节--感谢原博主 先上栗子 Student student1 = new Student();Student st ...

  5. java string jdk_Java.lang.String中JDK API 1.6.0摘要。

    Java.lang.String中JDK API 1.6.0摘要. String 类代表字符串.示例: String str = "abc"; 字符串是常量,它们的值在创建之后不能 ...

  6. java中equals,hashcode和==的区别

    原文地址http://blog.csdn.net/hla199106/article/details/46907725 1.== java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型 ...

  7. java面试题31:结构型模式中最体现扩展性的模式是()

    java面试题31:结构型模式中最体现扩展性的模式是() A:装饰模式 B:合成模式 C:桥接模式 D:适配器 蒙蔽树上蒙蔽果,蒙蔽树下你和我 结构型模式是描述如何将类对象结合在一起,形成一个更大的结 ...

  8. java字符串剪切函数,java用substring函数截取string中一段字符串,substringstring

    java用substring函数截取string中一段字符串,substringstring from  http://www.cnblogs.com/laiweili/archive/2012/11 ...

  9. java string的某个字符_JAVA如何提取String中字符串的某个字符 具体内容

    今天小编和大家分享JAVA如何提取String中字符串的某个字符,希望对大家有所帮助. 工具/材料 PC 操作方法 01 java中提取特定字符前的字符串: String str = "房估 ...

最新文章

  1. atlsoap.h”: No such file or directory
  2. 小能量汇聚成大能量_清体能量棒配料解析:小种子,大能量,藜麦和青稞
  3. 主题mysql_主题数据库(SubjectBase)
  4. 48-如何实现unix2dos功能
  5. python内置的集成开发工具是什么_python内置的集成开发工具是什么_后端开发
  6. c语言求两个有序表合成差集代码,两个有序链表求差集,合并为一个有序链表...
  7. Java工具类(获取当前主机操作系统名)
  8. 【python】语义分割(标签)黑色(单通道)图片的读取和显示方法
  9. python使用长ping命令_在Python中调用Ping命令,批量IP的方法
  10. EF学习笔记-2 EF之支持复杂类型的实现
  11. python frame框架,第12讲,frame 框架控件
  12. Proteus--软件简介及安装教程
  13. WNM6002 N通道增强功能MOS场效应晶体管
  14. 接口测试用例设计方法——接口测试用例思路梳理
  15. 阿里云 ADAM 迁移工具测试问题记录
  16. 微信小程序之个人界面编写(2023.5.9版)
  17. 在软件测试面试中,碰到这些「送命题」,大牛教你一招应对
  18. Vim 的 paste 模式
  19. Flowable No outgoing sequence flow of the exclusive gateway ‘xxx‘ could be selected for continuing
  20. 计算机系统的多级层次结构

热门文章

  1. Rxjava之操作符distinct和elementAt
  2. openfire 打包发布
  3. 看图说话:OpenGL模型矩阵和投影矩阵
  4. 算法---给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合
  5. 解决编译报错:duplicate value for resource
  6. android stadio svn 使用技巧
  7. Android 自定义debug.keystore
  8. Android Hanlder综合
  9. JNI 实战全面解析
  10. vcard java_关于vcard 文件数据格式,以备不时之需