聊一聊HashMap的put方法

1,343 阅读2分钟

HashMapjdk 1.8的时候修改过一次,但put方法的大致流程还是没有改变,下面说一下Put方法的大致流程:

大致流程

首先得到数组下标

不管是1.7还是1.8他们最开始都会先通过put传进来的key去通过哈希算法得到hashCode,通过hashCode进行操作再和数组长度进行计算从而得到数组下标。

数组下标为空,封装对象放入HashMap

得到数组下标之后就会去判断当前的数组下标位置元素为空,就会直接将传入的keyvalue封装成Node对象(注意:在JDK1.7当中是Entry对象,1.8之后是Node对象),其实就可以看成是一个keyvalue的对象。

把对象封装好后就会把当前的对象放入之前的数组下标当中,从而就把keyvalue存入到HashMap里面去了。

JDK1.7hashMap是通过数组 + 链表来实现的,而JDK1.8是通过数组 + 链表 + 红黑树来实现的。

数组下标不为空

如果数组下标不为空就需要分情况去进行讨论:

如果是jdk1.7,它会先去判断是否需要扩容,假如需要扩容那么就会先扩容,如果不需要扩容,则生成Entry对象,然后使用头插法添加到当前位置的链表中去,下面是1.7的源码:

image.png

如果是JDK1.8,会先判断当前位置上的Node对象类型,判断是链表还是红黑树。
1、如果是红黑树
会将keyvalue封装为一个红黑树节点并添加到红黑树中去,那么在添加红黑树这个过程中回去遍历这个树,然后判断树中是否存在当前key,假如树中存在该key则直接更新value
2、如果是链表:
会将当前的keyvalue封装成一个链表Node并通过尾插法插入到链表当中去。由于是尾插法,会先遍历链表同时在遍历的过程中判断是否key重复,如果重复就直接更新value,不重复的话遍历完之后会将新的Node对象插入到链表当中。

插入完之后会判断当前的节点个数,如果节点个数大于8并且哈希表长度大于64,则会把当前的链表转为红黑树,把对象插入到链表或者树中之后再判断是否需要进行扩容,如果需要扩容就再进行扩容的操作。

以上就是 HashMap 中 put 方法的大致过程。