本篇博客主要讲解了HashMap的put和resize操作
相关系列
基于JDK1.8的HashMap源码解析一(变量和构造器)
基于JDK1.8的HashMap源码解析三(get和remove以及迭代器)
HashMap节点解析
1 | // HashMap普通节点 |
HashMap拥有两种不同的节点,一种是普通的链表节点,一种是红黑树节点。红黑树比较难解析,因为HashMap源码跳过红黑树如何转换我们也能看懂,所以我打算以后放在一章专门的文章中讲解。普通节点很简单,其实就是我们大学数据结构课程常见的链表节点,我相信大家也能看懂,所以也不过多讲解了。
HashMap的put操作
1 | // 计算key的hash,这是一个"扰动函数"让高16和低16位进行异或,使分布更平衡,主要是为了防止差的hash函数 |
以上是HashMap的put操作的过程,总结如下:put首先判断是否初始化,没有就进行初始化操作。如果已经进行了初始化操作,根据hash判断插入的bucket中是否有值,没有则直接插入。如果有值,则循环遍历当前链表,找到是否存在相应的key,不存在执行插入操作,否则执行更新操作,期间插入过程到了红黑树的阈值则转换成红黑树。
HashMap的resize操作
1 | final Node<K,V>[] resize() { |
以上就是HashMap的resize()全过程了,每一步我都进行了详细的说明,现在系统的说一下它的全过程吧。因为HashMap的延时初始化策略,首先判断是否初始化,没有则根据构造方法进行初始化容量,同时也判断了是否超出最大容量的边界。正常扩容阶段则创建一个新的entry数组,同时将原entry数组中的每一个bucket中的元素通过尾插法(JDK1.7中使用得头插法)移动到新的bucket中。另外,hashMap没有对key为null的键值对进行特殊处理整个过程也很简单,只是一些细节方面可能需要理解一下。
好了,第二章的解析就到这里吧,我们下章再见,因为笔者不会画图,如果有同学画图厉害愿意帮忙把其中一些不好理解的操作画图给我那就太感激不尽啦。