@[TOC](`jdk 1.8 hashmap和1.7 hashmap区别 原理解析)
#在jdk中,目前使用比较多的主要是1.8,主要是因为1.8在1.7的基础上优化了很多内容,尤其是hashmap这个集合 在内部结构和实现上都是进行了优化和调整。下面主要讲了1.7发生死循环的原因和过程,以及1.8在添加元素的实现,最后总结了1.7和1.8的主要区别。
part1:hashmap比较
通过jdk的源码我们可以了解到,1.8在1.7的基础上,hashmap做了比较大的改动,下面具体说明:
1.7 hashmap
简单来说:*Entry数组+链表*的结构;插入数据使用*头插法*
我们都知道hashmap是线程不安全的,但是如果被用在了多线程上,1.7的hashma是有可能导致死循环,这是程序绝对不允许的。产生死循环的情况主要是在多线程下,进行put操作的时候,hashmap的Entry 链表有可能形成环形数据结构,一旦形成环形数据结构 Entry 的 next 节点永远不为空,就会产生死循环获取 Entry。
通过源码我们可以了解到,引发死循环,是在 HashMap 的扩容操作中。正常的扩容操作是这个流程。HashMap 的扩容在 put 操作中会触发扩容,主要是三个方法
综合来说,HashMap 一次扩容的过程:
1、取当前 table 的 2 倍作为新 table 的大小
2、根据算出的新 table 的大小 new 出一个新的 Entry 数组来,名为 newTable
3、轮询原 table 的每一个位置,将每个位置上连接的 Entry,算出在新 table上的位置,并以链表形式连接
4、原 table 上的所有 Entry 全部轮询完毕之后,意味着原 table 上面的所有Entry 已经移到了新的 table 上,HashMap 中的 table 指向 newTable
这里用一个实例说明死循环的产生:
【正常情况的扩容】:
现在 hashmap 中有三个元素,Hash 表的 size=2, 所以 key = 3, 7, 5,在 mod 2
以后都冲突在 table[1]这里了
按照源码中扩容的最后一步,把原数组移动到新数组的过程
对 table[1]中的链表来说,进入 while 循环,此时 e=key(3),那么 next=key(7),经过计算重新定位 e=key(3)在新表中的位置&#x