java中关于map的集合,想总结一下
JDK1.7组成:数组+链表 Entry的数组
JDK1.8组成:数组+链表+红黑树 Node的数组
JDK1.7链表采用的头插法:可能会产生链表环路,产生死循环的问题,造成cpu的使用率飙升。
JDK1.8链表采用的尾插法: 解决了链表环路问题 。
问题 :为什么会产生链表环路
因为在高并发下有多个线程,可能会发生多个线程对hashmap进行rehash(扩容)操作,扩容操作会对hash桶上的链表进行重新hash值%(length-1)操作,让链表上的元素找到新的存放位置,例如某个hash桶上的链表a->b->c(链表上的元素和指向关系),当进行扩容时a,b,c很巧又落到同一个hash桶上面了,线程1进行rehash操作先获得a(当然a->b->c,线程1把指向关系记录下来),很巧线程1刚好获取a时,cpu时间片用完了,线程2进行put操作是也发现hashmap需要扩容,也进行rehash操作,线程2成功进行rehash扩容使得hash桶上面链表执行c->b->a(尾插法会改变链表顺序,这也是为什么产生链表环路的问题),线程1重新获得cpu执行权,执行完a时,去执行b时(进行b->a操作)发现b已经指向a,a同时指向b,a->b,b->a,这样就会形成环。
详细请看这篇
JDK1.7
1.无参数 当创建HashMap时,当无参时,默认情况下: 负载因子为0.75f 默认Entry数组长度为16,默认阈值为12(16*0.75f):
2 .只输入初始容量 和 输入负载因子:Entry初始数组长度:2的n次幂的>=输入初始长度(n取最小),负载因子:为输入负载因子 ;
3 .只输入初始容量:负载因子为0.75f Entry初始数组长度:2的n次幂的>=输入初始长度(n取最小);
JDK1.8
为什么创建的数组初始长度必须为2的n次幂:
因为: