前言
HashMap作为Java中最常用的数据结构之一,在工作中使用HashMap的频率和你遇见NullPointException一样多。作为最常用的数据结构之一,我们都知道HashMap的容量为2次幂。当被问到为什么是2次幂时,大家应该都能回答出来,是为了将结点均匀分散到数组中。当容量为2次幂能够均匀分散结点,3次幂为什么不能?HashMap中如何解决Hash碰撞?在HashMap的构造方法中可以传入容量,如果传入非2次幂怎么办?看完这篇文章你会解决其中的疑问。
ps:代码来源于JDK1.8
正文
HashMap底层数据结构为数组+链表+红黑树。当我们向HashMap中插入一个对象,HashMap会通过Index映射算法得到该对象插入到数组的下标index。此时HashMap分辨这个位置有没有值以及值类型。如果index没有值,将当前对象放入当前位置。如果index有值,判断对象的key是否与该值的key相等(key的hash值相等以及key本身相等),如果key相等则覆盖该值,如果key不相等,将对象插入该值的尾部(链表和红黑树不同的处理)。
Index映射算法
int index = (n - 1) & hash
对于为什么采用&运算而不是%。1:&运算比%运算效率高很多;2:当n为2次幂,(n-1)&hash等同于hash%n。
如果HashMap的容量不是2次幂
假设当前HashMap的初始容量为17,即n等于17时。
1:n=17则n-1=16,16的二进制表示为0010000。
2:如果我现在向HashMap中插入两个键值对,key1=A,Key2=B。假设通过Hash算法得知A的hash值为1010110,B的Hash值为0110000
3:分别算出key等于A,B时所映射的index
0010000 0010000
1010110 01100