为什么 String hashCode 方法选择数字31作为乘子

参考文章:

hashCode 为什么乘以 31?深入理解 hashCode 和 hash 算法

https://www.jianshu.com/p/76c5215eda5c

为什么 String hashCode 方法选择数字31作为乘子

https://segmentfault.com/a/1190000010799123

为什么在定义hashcode时要使用31这个数呢?

https://blog.csdn.net/mingli198611/article/details/10062791

 总结:

定义hashcode时要使用31作为乘子主要有以下几个原因:

A、31 有个很好的性能,即用移位和减法来代替乘法,可以得到更好的性能: 31 * i == (i << 5)- i, 现代的 VM 可以自动完成这种优化。

B、31是一个奇素数,选择素数(质数)的好处就是如果我用一个数字来乘以这个素数,那么最终出来的结果也只能被素数本身和被乘数(以及被乘数的整除因子)还有1来整除!这样,以31作为乘子参与乘法计算得出的hashcode值,在后面进行取模(实际上是与运算时),得到相同index的概率会降低,即降低了哈希冲突的概率。

C、31作为一个既不太大又不太小的乘子,计算出来的hashcode值范围处于一个“适中”的区间,能够很好的降低哈希冲突,进行数据查找时可以提高效率。一方面,乘子太小容易导致计算出来的hashcode值范围处于一个“较小”的区间,在后面进行取模(实际上是与运算时),得到相同index的概率会升高,即哈希冲突的概率会提高;另一方面,乘子太大可能会导致相乘时造成数据溢出的概率增大。

D、31只占用5bits(11111B),相乘造成数据溢出的概率较小。

原文地址:https://www.cnblogs.com/blogfortang/p/hashcode_31.html

时间: 2024-11-09 12:06:42

为什么 String hashCode 方法选择数字31作为乘子的相关文章

【转】String hashCode 方法为什么选择数字31作为乘子

某天,我在写代码的时候,无意中点开了 String hashCode 方法.然后大致看了一下 hashCode 的实现,发现并不是很复杂.但是我从源码中发现了一个奇怪的数字,也就是本文的主角31.这个数字居然不是用常量声明的,所以没法从字面意思上推断这个数字的用途.后来带着疑问和好奇心,到网上去找资料查询一下.在看完资料后,默默的感叹了一句,原来是这样啊.那么到底是哪样呢?在接下来章节里,请大家带着好奇心和我揭开数字31的用途之谜. 2. 选择数字31的原因 在详细说明 String hashC

String hashCode 方法为什么选择数字31作为乘子

1. 背景 某天,我在写代码的时候,无意中点开了 String hashCode 方法.然后大致看了一下 hashCode 的实现,发现并不是很复杂.但是我从源码中发现了一个奇怪的数字,也就是本文的主角31.这个数字居然不是用常量声明的,所以没法从字面意思上推断这个数字的用途.后来带着疑问和好奇心,到网上去找资料查询一下.在看完资料后,默默的感叹了一句,原来是这样啊.那么到底是哪样呢?在接下来章节里,请大家带着好奇心和我揭开数字31的用途之谜. 2. 选择数字31的原因 在详细说明 String

JDK1.8源码学习-String-hashCode方法为什么选择数字31作为乘子

1. 背景 某天,我在写代码的时候,无意中点开了 String hashCode 方法.然后大致看了一下 hashCode 的实现,发现并不是很复杂.但是我从源码中发现了一个奇怪的数字,也就是本文的主角31.这个数字居然不是用常量声明的,所以没法从字面意思上推断这个数字的用途.后来带着疑问和好奇心,到网上去找资料查询一下.在看完资料后,默默的感叹了一句,原来是这样啊.那么到底是哪样呢?在接下来章节里,请大家带着好奇心和我揭开数字31的用途之谜. 2. 选择数字31的原因 在详细说明 String

hashCode方法与31

hash code 定位 一直有个概念就是,hash可以很快存取数据.但是具体的实现从没有深究过.最近想了解自定义hashCode方法,看到书上说到效率问题时,决定探究一下HashMap中hash的定位方式(HashSet内部也是借助HashMap来实现的). HashMap的数据存储结构 HashMap中的数据存储在Node数组table(Node[])中,最基本的Node是一个单向链表结构: static class Node<K,V> implements Map.Entry<K,

关于Java中String类的hashCode方法

首先来看一下String中hashCode方法的实现源码 1 public int hashCode() { 2 int h = hash; 3 if (h == 0 && value.length > 0) { 4 char val[] = value; 5 6 for (int i = 0; i < value.length; i++) { 7 h = 31 * h + val[i]; 8 } 9 hash = h; 10 } 11 return h; 12 } 在Stri

java String拼接的方法选择及性能分析

String 拼接的方法选择 在拼接静态字符串时,尽量用 +,因为通常编译器会对此做优化,如: String test = "this " + "is " + "a " + "test " + "string" 编译器会把它视为: String test = "this is a test string" 在拼接动态字符串时,尽量用 StringBuffer 或 StringBuilde

(转)java判断string变量是否是数字的六种方法小结

java判断string变量是否是数字的六种方法小结 (2012-10-17 17:00:17) 转载▼ 标签: it 分类: 转发 1.用JAVA自带的函数 public static boolean isNumeric(String str){ for (int i = 0; i < str.length(); i++){ System.out.println(str.charAt(i)); if (!Character.isDigit(str.charAt(i))){ return fal

详解equals()方法和hashCode()方法

前言 Java的基类Object提供了一些方法,其中equals()方法用于判断两个对象是否相等,hashCode()方法用于计算对象的哈希码.equals()和hashCode()都不是final方法,都可以被重写(overwrite). 本文介绍了2种方法在使用和重写时,一些需要注意的问题. 一.equal()方法 Object类中equals()方法实现如下: public boolean equals(Object obj) { return (this == obj); } 通过该实现

第八周:hashCode()方法 &amp; equals()方法

在Java语言中,equals()和hashCode()两个函数的使用是紧密配合的,要是自己设计其中一个,就要设计另外一个.在多数情况 下,这两个函数是不用考虑的,直接使用它们的默认设计就可以了.但是在一些情况下,这两个函数最好是自己设计,才能确保整个程序的正常运行.最常见的是当 一个对象被加入收集对象(collection object)时,这两个函数必须自己设计.更细化的定义是:如果你想将一个对象A放入另一个收集对象B里,或者使用这个对象A为查找一个元对象在收集对 象B里位置的钥匙,并支持是