简单分析HashMap源码

HashMap原理
目的:
单纯分析和学习hashmap的实现,jdk版本为 1.8
首先从put方法开始分析
简单分析HashMap源码
接下来就是putVal方法了:简单分析HashMap源码
简单分析HashMap源码
其中
1:指的是当新建hashmap实例,第一次增加键值对时,会通过resize()方法新建一个以内部类Node为元素的数组。
2:指的是在计算hash值与数组长度进行位运算后,得到键值对应存储的数据下标,并在判断该节点为空时直接新建一个Node去存储键值对,同时从初始化后的添加数据以及Node的构造函数可以看出hashmap对以null为key并未做限制,所以null可以作为hashmap的键。
3:指的是在获取相应的下标且该节点已经存在数据节点时,先判断key是否一致,一致则直接覆盖该Node节点,不一致则先遍历后续节点,若不存在相同的key则在该链表后面新增新的节点。
4:指的是当链表长度超过长度限制时,默认是8.则将链表转换为红黑树。此处先不讨论红黑树

还有一个比较重要的方法是resize()
简单分析HashMap源码
在初始化和达到数组容量*负载因子(默认0.75)的值时都会调用该简单分析HashMap源码
这里,
1指的是:当旧容量不为0时,即此时是扩容,会对旧容量数值进行位运算,直接将容量和扩容限制翻倍
2指的是:初始化,直接将默认容量设置为数组大小,默认容量为16,并根据负载因子计算出数组中使用空间达到多少时进行扩容。
简单分析HashMap源码
而resize中的这段代码则是将原数组中的数据移动至扩容后的容器当中。
在此,并未对链表转红黑树进行分析,有时间会继续研究。

而对于为什么hashmap的长度都是2的N次幂,从两个方面去分析

首先在hashmap中要想是数据均匀分布,也就是每个链表长度都差不多大小时,需要对计算出的hash值进行取模运算,一般是hash%length,而在hashmap对取模运算进行了优化,成为了hash&(length-1),而要使hash%length == hash&(length-1)成立,则length只能为2的N次幂

为什么这样能均匀分布减少碰撞呢?2的n次方实际就是1后面n个0,2的n次方-1 实际就是n个1;
例如长度为9时候,3&(9-1)=0 2&(9-1)=0 ,都在0上,碰撞了;
例如长度为8时候,3&(8-1)=3 2&(8-1)=2 ,不同位置上,不碰撞;
其实就是按位“与”的时候,每一位都能 &1 ,也就是和1111……1111111进行与运算
简单分析HashMap源码
到这里或许有人会问,那要是在hashmap初始化时指定大小,且指定的大小不为2的N次幂会怎么样?
实际上当我们在指定大小去初始化hashmap时,hashmap调用了一个方法,会自动的将大小转换为比当前指定值大的最近的2次幂
简单分析HashMap源码简单分析HashMap源码

在这里自己只是简单的分析了一部分,后面找到了一篇比较详细的博客,大家可以参考一下
https://www.cnblogs.com/zhaojj/p/7805376.html