首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

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

HashMap hash 算法实现原理(为什么右移 16 为什么使用 ^ 异或) 6. HashMap 为什么使用 & 与运算代替模运算? 7....前言 HashMap 高度依赖 hashcode hash 算法,虽然在很多书里面,都说这是数学家应该去研究事情,但我想,程序员也应该了解他怎么实现为什么这么做?...所谓素数:质数又称素数,指在一个大于1自然数,除了1此整数自身外,没法被其他自然数整除数。...HashMap hash 算法实现原理(为什么右移 16 为什么使用 ^ 异或) 好了,知道了 hashCode 生成原理了,我们要看看今天主角,hash 算法。...到这里,我们提了一个关键问题: HashMap 容量为什么建议 2幂次方?正好可以上面的话题接上。 我们说,hash 算法目的是为了让hash均匀分布在桶(数组),那么,如何做到呢?

2.4K21

深入理解 hashcode hash 算法

为什么右移 16 为什么使用 ^ 异或) HashMap 为什么使用 & 与运算代替模运算?... hashCode 方法注释已经说明了 ),我知道,HashMap 之所以速度快,因为他使用散列表,根据 key hashcode 生成数组下标(通过内存地址直接查找,没有任何判断),时间复杂度完美情况下可以达到...HashMap hash 算法实现原理(为什么右移 16 为什么使用 ^ 异或) 好了,知道了 hashCode 生成原理了,我们要看看今天主角,hash 算法。...使用数组长度减一 与运算 hash 。这行代码就是为什么要让前面的 hash 方法移位并异或。...并且得到结果取决于 hash 。因为 hash 1,那么最终结果也是1 ,hash 0,最终结果也是0。 7. HashMap 容量为什么建议 2幂次方?

2.3K31
您找到你想要的搜索结果了吗?
是的
没有找到

细品Java8hashCode方法

主要用途 hashcodeObject函数,所有都拥有的一个函数,主要返回每个对象hash,主要用于哈希表,如HashMap、HashTable、HashSet。...JavaHashCode实现: 在JavaObject.class中有hashCode方法,方法native 方法,实现就是在JVM实现,也就是说他使用C语言实现。...实现方式:OpenJDK8 默认hashCode计算方法通过当前线程有关一个随机数+三个确定,运用Marsaglia’s xorshift scheme随机数算法得到一个随机数。...* 因为该表使用2幂次掩码,所以*仅在当前掩码上方中发生变化*哈希集将**总是发生冲突。 (众所周知示例Float键集*在小表中保存连续整数。)...由于许多常见哈希集*已经合理地分布了(因此不能从*扩展*受益),并且由于我们使用树来处理bin大量*冲突集,因此我们仅以*最便宜&方式对一些移位进行XOR运算,减少系统损失,以及*合并最高位影响

55630

硬核 - Java 随机数相关 API 演进与思考(上)

API 底层实现以及他们属性,性能以及使用场景,如何选择随机算法等等,并对 Java 随机数对于 Java 一些未来特性适用进行展望 这是第一篇。...这是一个简单优化, 实际优化要比这个复杂多。 初始化这个黑盒时候,一般采用一个 SEED 进行初始化,这个 SEED 来源可能多种多样,这个我们先按下不表,先来看一些这个黑盒中一些算法。...即根据当前 Seed 乘以一个系数 A,然后加上一个偏移 B,最后按照 C 进行取余(限制整体在一定范围内,这样才能选择出合适 A B,为什么要这么做后面会说),得出随机数,然后这个随机数作为下次随机种子...异或运算是最常见单比特线性函数:对寄存器某些进行异或操作后作为输入,再对寄存器每个 bit 进行整体移位。...Java 17 之前一般如何生成随机数以及对应随机算法 首先放出算法与实现对应关系: 使用 JDK API 1.使用 java.util.Random 基于它 API: Random random

70620

HashMap 这一篇就够了

二狗:threshold 除了用于存放扩容阈值还有其他作用吗? 囧辉:在我们新建 HashMap 对象时, threshold 还会被用来存初始化容量。...二狗:你说 HashMap 默认初始容量 16,为什么16而不是其他? 囧辉:(这是什么煞笔问题)我认为16原因主要是:162N次方,并且一个较合理大小。...囧辉:负载因子默认0.75。 二狗:为什么0.75而不是其他? 囧辉:(又问这种憨逼问题)这个也是在时间空间上权衡结果。...囧辉:拿到 key hashCode,并将 hashCode 高16 hashCode 进行异或(XOR)运算,得到最终 hash 。...2)计算 table 初始容量方式发生了改变,老方式从1开始不断向左进行移位运算,直到找到大于等于入参容量;新方式则是通过“5个移位+或等于运算”来计算。

98720

HashMap扩容流程

HashMap扩容,又被很多人叫rehash、重哈希,我本人很反对这个叫法,事实上HashMap扩容时候,Node存储Keyhash并没有发生变化,只是Node位置发生了变化。...初始化其实是resize方法实现。...因为这里我是以JDK1.8源码作为样本分析,如果我没记错的话,JDK1.7还存在rehash方法,但是JDK1.8已经改名叫resize方法了,那我们就不管JDK1.7如何实现扩容,直接上JDK1.8...= 5 key4 00110101 00001101 = 21 到这应该能明白,resize方法里lo列表hi列表是什么意思了,其实就是看key高一哈希1还是0,来决定是放到哪个队列里。...移位HashMap如下图: 这里HashMap非常精妙实现了扩容,没有重新计算对象哈希,甚至连下标的重新计算也只需要进行相与计算(hash高位 & newCap-1 )。

3.5K30

【C++】继承 ⑥ ( 继承构造函数析构函数 | 类型兼容性原则 | 父指针 指向 子类对象 | 使用 子类对象 为 父对象 进行初始化 )

地方 , 都可以使用 " 公有继承 " 派生 ( 子类 ) 对象 替代 , 该 派生 ( 子类 ) 得到了 除 构造函数 析构函数 之外 所有 成员变量 成员方法 ; 功能完整性 :..." 公有继承 " 派生 ( 子类 ) 本质上 具有 基 ( 父 ) 完整功能 , 使用 可以解决问题 , 使用 公有继承派生 都能解决 ; 特别注意 : " 保护继承 " ..." 私有继承 " 派生 , 不具有 基 完整功能 , 因为 最终继承 后派生 , 无法在 外部调用 父 公有成员 保护成员 ; 2、类型兼容性原则应用场景 " 类型兼容性原则..." 应用场景 : 直接使用 : 使用 子类对象 作为 父对象 使用 ; 赋值 : 将 子类对象 赋值给 父对象 ; 初始化 : 使用 子类对象 为 父对象 初始化 ; 指针 : 父指针 指向...); } 2、使用 子类对象 为 父对象 进行初始化 定义父对象 , 可以直接使用 子类对象 进行初始化操作 ; // II.

20720

HashMap在JDK1.7以及JDK1.8区别?

1.2.插入键值对: 当调用put(key,value)时,经历以下步骤: ①计算key哈希(详见我之前一篇写HashMap底层哈希计算文章),然后将哈希与数组长度-1进行与运算,得到应该存储数组下标索引...1.4.Hash算法: 1.8版本直接用对应OBjecthash计算方法。避免hash碰撞运算即为简单:向右移位,并进行异或。hash用final修饰,一旦确定不再更改。...3.JDK1.8一些其他细节 3.1.加载因子:在进行扩容时,会进行阈值判断,这个阈值大小通过当前数组容量一个加载因子进行确定。...java源码关于为什么树化解释: 由于TreeNodes大小大约是常规节点两倍,因此我们仅在容器包含足够节点以保证使用时才使用它们(参见 TREEIFY_THRESHOLD )。...3.5.为什么把链表转化为红黑树阈值8,而不是6、7或者不是20呢? 这个问题其实3.3.差不多,但3.3只回答了一部分。 即为什么不是6,综合了性能时间效率。 那为什么不是7?

44500

Java集合 | 重识HashMap

下面将对照HashMap源码来分析其原理实现。...HashMap容器创建,采用了延迟初始化,创建容器时,只是指定了负载系数(loadFactor)扩展阈值(threshold),真正创建容器,在put第一个元素时候;而HashMap容量被指定为...,根移位之前数做一次按或操作; 最后就会得到都是1数,这个数再加1,还是2整数平方倍,也就是比指定数大最小2整数平方倍 两个问题: 为什么每次1、2、4、8、16移动?...而容器容量为2整数平方倍,再减一的话,转化成二进制除最高位左面的0,其他所有都是1,这样做与运算得到结果,必然落在length内,而且效率要比取模运算快。...key相等元素;删除操作包含查找操作,所以链表时间复杂度O(n) 红黑树:稍后分析 红黑树 为什么要将链表进行树化操作呢?

74330

​Java Map那些巧妙设计

初始化与懒加载 初始化时候只会设置默认负载因子,并不会进行其他初始化操作,在首次使用时候才会进行初始化。...而在实现,JDK并没有直接使用Objectnative方法返回hashCode作为最终哈希,而是进行了二次加工。...以下分别为HashMap与ConcurrentHashMap计算hash方法,核心计算逻辑相同,都是使用key对应hashCode与其hashCode右移16结果进行异或操作。...整个过程找到cap对应二进制中最高位1,然后每次以2倍步长(依次移位1、2、4、8、16)复制最高位1到后面的所有低位,把最高位1后面的所有全部置为1,最后进行+1,即完成了进位。...正在被其他线程锁定,那当前线程也没必要再等待了,直接尝试使用baseCount进行累加。

60110

面渣逆袭:HashMap追魂二十三问

HashMap哈希函数先拿到 key hashcode,一个32int类型数值,然后让hashcode高16低16进行异或操作。...n次幂时,(n-1)2进制也就是1111111***111这样形式,这样与添加元素hash进行运算时,能够充分散列,使得添加元素均匀分布在HashMap每个位置上,减少hash碰撞。...HashMap基于数组+链表红黑树实现,但用于存放key桶数组长度固定,由初始化参数确定。 那么,随着数据插入数量增加以及负载因子作用下,就需要扩容来存放更多数据。...20.HashMap 内部节点有序吗? HashMap无序,根据 hash 随机插入。如果想使用有序Map,可以使用LinkedHashMap 或者 TreeMap。...( HashSet 源码⾮常⾮常少,因为除了 clone() 、 writeObject() 、 readObject() HashSet⾃⼰不得不实现之外,其他⽅法都是直接调⽤ HashMap

34130

Glide都在用LruCache,你学会了吗?

该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历时间 t,当须淘汰一个页面时,选择现有页面其 t 最大,即最近最少使用页面予以淘汰。...但是问题依旧存在,initialMaxSize作用是什么?,我们能够知道maxSize一个用于控制容量大小。...,但是我觉得还是没啥用,可是是我太菜了吧,这个方法没有其他调用它方法,一个我们直接在使用过程中使用,可能和数据多次使用一个保存之类问题相关联把,场景的话也就类似Glide图片缓存加载把。...做一个猜想好了,既然使用了put()才会造成双向链表数据变换,那我们就应该是需要进入对LinkedHashMap.put()方法中进行查询。...当然有兴趣探索读者们,我需要提一个醒,就是这次调用不可以直接进行对put()进行查询,那样只会调用到一个接口函数,或者抽象函数,最适合方法还是使用我们断点来进行探索查询。

53440

HashMap深度解析(二)

看第14-16行代码,这里做了一个移位运算,保证了初始容量一定为2幂,假如你传5,那么最终初始容量为8。源码运算随处可见啊=。=!        ...加载因子过高虽然减少了空间开销,但同时也增加了查询成本(在大多数 HashMap 操作,包括 get put 操作,都反映了这一点,可以想想为什么)。...HashMap所有集合视图所返回迭代器都是快速失败(fail-fast),在迭代器创建之后,如果从结构上对映射进行修改,除非通过迭代器自身 remove 或 add 方法,其他任何时间任何方式修改...至于为什么通过迭代器自身remove或add方法就不会出现这个问题,可以参考我之前文章List比较好玩操作第三个第四个示例。        ...HashMap线程不安全实现,而HashTable线程安全实现,关于线程安全与不安全可以参考我之前文章Java线程(一):线程安全与不安全,所谓线程不安全,就是在多线程情况下直接使用HashMap

79800

HashMap 源码详细分析(JDK1.8)

一、概述 本篇文章我们来聊聊大家日常开发中常用一个集合 - HashMapHashMap 最早出现在 JDK 1.2,底层基于散列算法实现。...HashMap 允许 null 键 null ,在计算哈键哈希时,null 键哈希为 0。HashMap 并不保证键值对顺序,这意味着在进行某些操作后,键值对顺序可能会发生变化。...另外,需要注意HashMap 是非线程安全,在多线程环境下可能会存在问题。 在本篇文章,我将会对 HashMap 中常用方法、重要属性及相关方法进行分析。...需要说明HashMap 源码可分析点很多,本文很难一一覆盖,请见谅。 二、原理 上一节说到 HashMap 底层基于散列算法实现,散列算法分为散列再探测拉链式。...通过移位异或运算,可以让 hash 变得更复杂,进而影响 hash 分布性。这也就是为什么 HashMap 不直接使用键对象原始 hash 原因了。

1.8K240

Glide都在用LruCache,你学会了吗?

该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历时间 t,当须淘汰一个页面时,选择现有页面其 t 最大,即最近最少使用页面予以淘汰。...,但是我觉得还是没啥用,可是是我太菜了吧,这个方法没有其他调用它方法,一个我们直接在使用过程中使用,可能和数据多次使用一个保存之类问题相关联把,场景的话也就类似Glide图片缓存加载把。...也就是最近使用数据应该调换到最后开始位置,他到底在哪里进行处理呢?...做一个猜想好了,既然使用了put()才会造成双向链表数据变换,那我们就应该是需要进入对LinkedHashMap.put()方法中进行查询。...当然有兴趣探索读者们,我需要提一个醒,就是这次调用不可以直接进行对put()进行查询,那样只会调用到一个接口函数,或者抽象函数,最适合方法还是使用我们断点来进行探索查询。

37040

HashMap 源码详细分析(JDK1.8)

一、概述 本篇文章我们来聊聊大家日常开发中常用一个集合 - HashMapHashMap 最早出现在 JDK 1.2,底层基于散列算法实现。...另外,需要注意HashMap 是非线程安全,在多线程环境下可能会存在问题。 在本篇文章,我将会对 HashMap 中常用方法、重要属性及相关方法进行分析。...需要说明HashMap 源码可分析点很多,本文很难一一覆盖,请见谅。 二、原理 上一节说到 HashMap 底层基于散列算法实现,散列算法分为散列再探测拉链式。...HashMap使用了拉链式散列算法,并在 JDK 1.8 引入了红黑树优化过长链表。数据结构示意图如下: ? 对于拉链式散列算法,其数据结构由数组链表(或树形结构)组成。...通过移位异或运算,可以让 hash 变得更复杂,进而影响 hash 分布性。这也就是为什么 HashMap 不直接使用键对象原始 hash 原因了。

38530

面试必备之HashMap底层设计与实现详解

HashMap取值非常快”等等。这个时候说明他已经很熟练使用HashMap工具了。 问:“你知道HashMap 在putget时候怎么工作吗?”...6、HashMapHash计算碰撞问题 HashMaphash计算时先计算hashCode(),然后进行二次hash。...大体意思说选择31是因为它是一个奇素数,如果它做乘法溢出时候,信息会丢失,而且当2做乘法时候相当于移位,在使用时候优点还是不清楚,但是它已经成为了传统选择,31一个很好特性就是做乘法时候可以被移位减法代替时候有更好性能体现...例如31i相当于是i左移5减去i,即31i == (i<<5)-i。现代虚拟内存系统都使用这种自动优化。 现在进入正题,HashMap为什么还要做二次hash呢?...HashMap是否在内部或被其它线程修改,如果modCountexpectedModCount不一样,证明有其他线程在修改HashMap结构,会抛出异常。

37520

面渣逆袭:Java集合连环三十问

集合相关接口都在java.util,主要分为3种:List(列表)、Map(映射)、Set(集)。...HashMap哈希函数先拿到 key hashcode,一个32int类型数值,然后让hashcode高16低16进行异或操作。...HashMap基于数组+链表红黑树实现,但用于存放key桶数组长度固定,由初始化参数确定。 那么,随着数据插入数量增加以及负载因子作用下,就需要扩容来存放更多数据。...27.HashMap 内部节点有序吗? HashMap无序,根据 hash 随机插入。如果想使用有序Map,可以使用LinkedHashMap 或者 TreeMap。...( HashSet 源码⾮常⾮常少,因为除了 clone() 、 writeObject() 、 readObject() HashSet⾃⼰不得不实现之外,其他⽅法都是直接调⽤ HashMap

61220

集合系列 Map(十二):HashMap

HashMap Map 基于哈希散列算法实现,其在 JDK1.7 采用了数组+链表数据结构。在 JDK1.8 为了提高查询效率,采用了数组+链表+红黑树数据结构。...没错,HashMap 在创建时候并不会进行数据初始化,而是在真正插入时候才进行初始化操作。这一部分代码在 resize (扩容)方法,我们后续会讲到。...HashMap 扩容机制与其他变长集合套路不太一样,HashMap 按当前桶数组长度2倍进行扩容,阈值也变为原来2倍(如果计算过程,阈值溢出归零,则按阈值公式重新计算)。...这是因为扩容后,参与模运算位数由4变为了5。由于两个 27 35 两个节点第5不一样,所以两个 hash 算出结果也不一样。...3.1.3.1 就是判断如果 e.hash & oldCap = 0(即原 hash 某一0,那么其位置就不变),那么就放在 loTail 为首链表,这个链表存扩容后放置在原来桶位置节点

43741

HashMap你了解多少

在日常开发工作HashMap使用频率相当高一个工具,同时「HashMap底层实现原理,也成了面试题中常客。最近又翻看了一下源码,做个记录。(本文都是基于jdk1.8源码) 1....❝在object,hashcode()方法本地方法,返回对象地址,而objectequals()方法比较也是两个对象地址,如果equals()相等,说明两个对象地址也相等,当然...2、「运算Hash」这类型Hash函数通过利用各种运算(常见移位异或)来充分混合输入元素。...作为不可变天生线程安全。 6. HashMaphash函数怎么实现为什么不直接将key作为哈希而是与高16做异或运算?还有哪些hash函数实现方式?...7. hashMap什么时候需要进行扩容,扩容resize()又是如何实现

21320
领券