个体户营业执照科研做企业网站吗,中国免费最好用建站cms,空间域名免费申请,网站建设顺序HashMap1.7和1.8的区别 1.JDK1.7用的是头插法#xff0c;而JDK1.8及之后使用的都是尾插法
那么为什么要这样做呢#xff1f;因为JDK1.7是用单链表进行的纵向延伸#xff0c;当采用头插法时#xff0c;再多线程环境下并发扩容的时候#xff0c;会容易出现环形链表死循环问…HashMap1.7和1.8的区别 1.JDK1.7用的是头插法而JDK1.8及之后使用的都是尾插法
那么为什么要这样做呢因为JDK1.7是用单链表进行的纵向延伸当采用头插法时再多线程环境下并发扩容的时候会容易出现环形链表死循环问题。但是在JDK1.8之后使用尾插法能够避免出现逆序且链表死循环的问题。
2.扩容流程不同
1.8是扩容前插入键值连同旧的键值一起转移一起计算1.7是扩容后扩容后进行插入旧数据转移到新的数组之后然后再单独计算插入的位置。为什么1.8是插入之后再整体计算扩容主要是为了减少红黑树和链表来回转换的频率
3.扩容后数据存储位置的计算方式也不一样
要说清楚这个先得说说HASHMAP如何求桶的位置
HashMap求桶的位置一共分为三个过程
1求key的hashcode 2将hashcode的高16位和低16位进行异或操作。
至此我们完成了hash方法求得了该元素的hash值。源码在下方
static final int hash(Object key) {int h;return (key null) ? 0 : (h key.hashCode()) ^ (h 16);
}
3(n - 1) hash 将hash值与length-1进行与操作求桶的位置 if ((p tab[i (n - 1) hash]) null)tab[i] newNode(hash, key, value, null);
无论是JDK7还是JDK8HashMap的扩容都是每次扩容为原来的两倍即会产生一个新的数组newtable我们需要把原来数组中的元素全部放到新的只不过元素求桶的位置的方法不太一样。
在JDK7中就是按照我上述写的三个步骤重新对元素求桶的位置但是第三步与的值是新的数组的长度-1也就是newCap-1。
但是JDK8中就不是和newCap而是直接和oldCap进行与运算也就是与旧数组的长度oldCap进行与操作。下面的是伪代码
if ((e.hash oldCap) 0) {
newTab[j] loHead;
}else{
newTab[j oldCap] hiHead;
}
与oldCap与的结果如果是0那么就代表当前元素的桶位置不变。 反之那么扩容后桶的位置就是原位置原数组长度oldCap
4.数据结构不同
JDK1.7的时候使用的是数组 单链表的数据结构。但是在JDK1.8及之后时使用的是数组链表红黑树的数据结构当链表的深度达到8的时候也就是默认阈值就会自动扩容把链表转成红黑树的数据结构来把时间复杂度从On变成OlogN提高了效率小于6的时候又会转换为链表。为什么是8容器中节点分布在hash桶中的频率遵循泊松分布桶的长度超过8的概率非常非常小。