开足码力,码动人生,本文首发公众号【 Craig无忌 】,关注这个一言不合就开车的的代码界老司机
本文 GitHub上已经收录 github.com/BeKingCodin… , 一线大厂面试核心知识点、我的联系方式和技术交流群,欢迎Star和完善
前言
HashMap 作为 Java 语言中经典的数据结构之一,在面试中出现的频率几乎是最多的。它本身有太多的点可以深入探讨,这里不得不佩服大神 Doug Lea 的水平,每一次读源码都感叹它的优美。
如果大家仔细看过源码的话,应该知道 HashMap 大小的初始值为16,如果要指定的话,必须是2的指数幂。
但是你有没有想过为什么要这样设计呢?其实背后的思路很巧妙,本篇文章我们就来探索一下。
正文
我们知道 HashMap 是一个 K-V 存储的数据结构,在 JDK8 之后升级为数组 + 链表 + 红黑树的形式。
当需要对KV对放入 HashMap 中时,会按照下面的步骤来完成:
(1)首先对 Key 做哈希运算,得到它的哈希值;
(2)根据哈希值值,按照 HashMap 的寻址算法得到 index 值,也就是对应应该放入数组的位置;
index = hashcode & (length -1)
(3)如果发生哈希冲突,则会通过拉链法来处理;
而 HashMap 为什么容量必须是 2 的指数幂就是因为由上述的寻址算法要求的。
当 HashMap 的容量为 2 指数幂时,那么length -1 后,十进制换算成二进制你会发现每一位都是1。
比如我们假设容量 length=32,则 length-1后为31,转换为二进制是 11111。这样当 hashcode 和它进行与运算(两个同时为1,结果为1,否则为0)的时候,可以得到( 0 ~ 31 )范围内的每一个值。
但如果容量不为 2 的指数幂,比如 length=50,那么 length -1=49,换算为二进制是110001。
那么无论一个 hashcode是什么, 和 49 (即110001)与运算后的结果只能为以下几种,因为中间的三位肯定是零:
000000 : 0
000001 :1
010000 :16
010001 :17
100000 :32
100001 :33
110000 :48
110001 :49
欢迎大家关注我的公众号「Criag无忌」
我是无忌,创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!