在上一篇文章我们说过HashMap在jdk1.7的时候由于线程安全问题会导致环链的形成https://juejin.cn/post/6844903992745525256,那么在1.8是怎么解决这个问题的呢??我们带着这个问题进入源码

先看看resize()方法前面一部分的,主要是对扩容后的HashMap的各种变量进行赋值,而且可以看待新的Map的长度是之前的2倍。前提是小于最大的长度限制。
重点看下图

整个方法太长我就截了2张图。这里首先设置了4个空的节点 loHead,loTail,hiHead,hiTail。首先会遍历旧的table数组,然后再遍历这个节点下的链表。如果这个节点的第一个元素为 null,或者这个节点只有一个元素,那么就用这和元素的 hash值与 (新的table的长度-1)做【与】运算,然后得到在新的table的桶的位置,将这个元素放进去。如果这个节点的是个树(对不起,能力有限,暂时不明白,其实能形成红黑树的几率非常非常小,在源码中有下面这样的一段注释,就是当链表长度等于8的时候才会转红黑树,但是链表长度等于8的几率是 0.00000006,这个几率几乎是不可能发生的)
所以我们最主要是分析下面这段代码
do{}while()循环体有二个判断,首先得到这个元素,然后用这个元素的hash值和老的table长度做与运算。
接下来我画图来说明吧,假如说现在我们的table结构是这样的,如下图

那么现在do{}while()循环就是遍历第二个节点了
其实我们知道扩容只是将这三个元素放到新的table中去,所以我们要知道的就是到底怎么放才能解决环链问题。
在这个do{}while)()循环体结束之后这三个节点会产生如下几种情况【当然还不止】
第一种:
第二种:
第三种:
它就是将整个链表拆成了2份【也有可能是一份】主要是根据下面这个来判断的
也就是说一个链表被分成了二个链表,就比如上面三种情况一样,链表分好了,但还是没有放,看下面代码

上面分好的链表直接移到新的table的某个节点下,也就是将整个链表移动过去。比如说旧的table长度是16,扩容后是32.如果第一个链表放到了5这个位置,那么另外一个链表就放到(5+16)也就是21这个位置。所以在将整个链表移动过去了那么是不会形成环链的。