HashMap数据结构
数组+链表,如果产生hash冲突,后进的值放入链表的头,默认数组的大小为16,加载因子为0.75,阈值为12,当大于12的时候进行扩容,进行rehash操作,原来的数组大小变为32,加载因子不变。
hashMap线程不安全,扩容时候读取会导致死循环。
比如原来Map的阈值是2连个元素,存在冲突链3--7--null
A线程和B线程都往map put元素
A读取快照
B 准备put进行扩容 ,假设扩容后存放位置不变,那么扩容后是7--》3--》null
A进行扩容,取出3元素,再取7,变成7--3,但是再取7的时候B已经把next变成了3
最后的冲突链变成了7《--》3,取的时候陷入死循环,挂
1.8优化,key对值大于8使用红黑树
1,扩容时候,原来所有的数要重新取摸hash一把,因为扩容的数组是2的幂数,所以原来key的位置要不在原来位置不变,要不向下移一个幂数 ,可以根据key的二进制的高为是1还是0进行判断,如果是1位置就在原来位置基础上+原来的数组的长度,比如
原来的数组的长度是16
10000
5 0000 0101 存放位置为5
21 0001 0101 存放位置为5
扩容数组变成32
100000
5 0000 0101 高位是0 ,存放在原来位置
21 0001 0101 高位为1 ,存放位置为5+2的4次幂
数组扩容变成64
1000000
5 000 00101 高位是0 ,存放在原来位置
21 000 10101 高位是0 ,存放在原来位置