HashMap 容量为何要是 2 的指数幂?

405 阅读2分钟

开足码力,码动人生,本文首发公众号【 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无忌」


我是无忌,创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见! 在这里插入图片描述