Java HashMap

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 ,存放在原来位置

你可能感兴趣的:(Java HashMap)