由 数组+链表 的结构改为 数组+链表+红黑树。 拉链过长会严重影响hashmap的性能,所以1.8的hashmap引入了红黑树。 在链表元素数量超过8时改为红黑树,少于6时改为链表,中间7不改是避免频繁转换降低性能。 相对于链表,改为红黑树后碰撞元素越多查询效率越高。链表O(n),红黑树O(logn)。优化了高位运算的hash算法:h^(h>>>16) 将hashcode无符号右移16位,让高16位和低16位进行异或。扩容resize后,元素要么是在原位置,要么是在原位置再移动2次幂的位置,且链表顺序不变。 不需要重新计算hash,只需要根据原来hash值新增的bit是1还是0分别放进两个链表lo和hi(非红黑树的情况)里,0的话索引没变,1的话索引变为原索引加原来的数组长度。 因此,我们在扩充HashMap的时候,不需要像JDK1.7的实现那样重新计算hash,只需要看看原来的hash值新增的那个bit是1还是0就好了,是0的话索引没变,是1的话索引变成“原索引+oldCap”。(每个节点e的hash早就计算好,并保存在final hash中)。通过if ((e.hash & oldCap) == 0)判定前面那个bit是不是1,如果是1则加上oldCap。
static class Node<K,V> implements Map.Entry<K,V> {} jdk1.8中用Node替代了Entry。
因为用的尾插法所以新数组链表不会倒置,多线程下不会出现死循环。