JDK1.8和JDK1.7相比差异不是很大,但是有几个重要的区别:
JDK1.8的数据结构:
JDK1.8是针对JDK1.7优化了查询,因为当哈希冲突严重时,在桶上形成的链表会越来越长,这样在链表上
查询时效率就越来越低,时间复杂度为O(n).因此1.8中重点优化了这个查询效率。
在哈希冲突时,数组上存储的结构可能是链表也可能是红黑树。static final int TREEIFY_THRESHOLD = 8;作为
是否把链表转换成红黑树的阈值。
操作put()方法时:
根据当前 key 的 hashcode 定位到具体的桶中并判断是否为空,为空表明没有 Hash 冲突就直接在当前位置创建一个新桶即可。
如果当前桶为红黑树,那就要按照红黑树的方式写入数据。
如果是个链表,就需要将当前的 key、value 封装成一个新节点写入到当前桶的后面(形成链表)。
接着判断当前链表的大小是否大于预设的阈值,大于时就要转换为红黑树。
遍历存在相同的key时把值覆盖。
最后判断是否需要扩容。
操作get()方法时:
首先将 key hash 之后取得所定位的桶。
如果桶为空则直接返回 null 。
否则判断桶的第一个位置(有可能是链表、红黑树)的 key 是否为查询的 key,是就直接返回 value。
如果第一个不匹配,则判断它的下一个是红黑树还是链表。然后按照链表或者红黑树的方法返回匹配值。
对于高并发下的死循环问题:
因为1.7中链表使用尾插法,所以在高并发的情况下查找某个key会导致死循环的问题;
而1.8中链表使用头插法,所有在高并发的情况下不会导致死循环。
1.7原理:https://blog.youkuaiyun.com/Deronn/article/details/100658819