java 7 的hashmap 是数组 + 链表
1.8 加入了红黑树,提高了(10%~15%)
数组查询快,因为有下标,但是插入和删除慢,
链表删除快,指定下标, 但是查找慢,因为要全扫描,
红黑树,每一个节点都有一个子节点,
hashmap 初始容量是16
2的指数次幂
数组加到链表的时候都是 object.hashcode ,
hash = hashcode 564564654
hash%16 ={0-15}
然后放进链表,
如果hashcode值一样会发生hash碰撞,
链表冲突,
java 7 利用的是头插法, 如果重复就插入到前面
但是没有%运算,
采用的位运算,
因为位运算的效率比取模效率高
h& (length-1 ) 效率>取模运算
10000次
位运算是5256毫秒
取模运算是 23229毫秒
h& (length-1 )几乎等价于取模预算
h& (length-1 ) [0-15] 必须数组长度是2的指数次幂
hashmap为啥线程不安全?
数据丢失,会产生死锁
1.7 transfer 方法 这里发生的死锁
1.8 优化了改成了头部插入法,避免了死锁的形成
1.8 头部插入法
通过与运算, 来判断是是高位还是低位, loTail hiTail
通过转换成二进制判断,解决链表过长问题,解决了死锁形成
loadFactory 负载因子, 0.75f取了最优值
为什么是0.75 ,
StackOverflow 国外网站,程序猿看的发现,
通过牛顿二项等式算出来是0.69 ,其实应该是0.693左右,
c#, .net 取的0.72 loadFactory
链表转红黑树, 初始值是8
当数组长度<64时,优先扩容 (在hashmap里的 treeifyBin 方法和 computeIfAbsent(扩容转红黑树) 方法,,如果拿到8优先扩容,大于等于64时才转红黑树)
链表转红黑树, 阈值是8 , 实际的链表长度是9 , 直接扩容,