我并没有和HashMap杠上,想着重新开始写点技术的东西,就拿HashMap开头了。最近开始重新学习数据结构和算法,其中有些东西学完之后,对于HashMap的理解和运用又有新的认识。虽然之前运用HashMap也有这样用过,但是知道了方法论,才发现这样使用的好处。
上一期我写过HashMap,写的是JDK8之前的Hash,现在都JDK15了,大家有兴趣可以去看一下源计划之从HashMap认识数据结构
JDK8的HashMap
现在大家基本上使用的JDK版本都是8以上,所以JDK8的HashMap更有实用价值,那么JDK8之后,针对HashMap做了哪些优化呢?
hash方法变化
JDK8之后的Hash算法:
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
JDK7的hash算法:
static int hash(int h) {
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
可以发现,JDK8之后使用了三元运算符,计算了2次,一次右移运算,一次异或运算。
而JDK7中的进行了4次右移运算,进行了四次扰动,JDK在Hash算法上提高了性能。
存储数据结构的变化
JDK8之前,发生了Hash碰撞之后,同一个node节点,将存储在链表中。
JDK8之后发生的变化
当同一个node节点存储数据大小达到8之后,存储结构会将链表变成红黑树。
那么node节点存储数据大小一开始达到了8,后来map数据减少,该node数据大小小于8,node节点的存储结构是否还是红黑树?
- 答案:node有可能是红黑树,也有可能会退化到链表结构,因为退化阈值并不是8,而是6。
下面的HashMap源码可以发现,当node节点数据大小小于6的时候,才会将红黑树转化为链表结构。
static final int TREEIFY_THRESHOLD = 8;
static final int UNTREEIFY_THRESHOLD