HashMap
的使用
在开发中经常使用到 HashMap
,分析一下 HashMap
带参的构造方法
1 | /** |
一个参数的构造方法,传入的参数是初始大小,最终调用两个参数的构造方法,传入初始大小和负载系数。默认的负载系数 DEFAULT_LOAD_FACTOR
是 0.75f
.调用tableSizeFor(int)
传入初始大小值算出threshold
,具体的 tableSizeFor(int)
方法,threshold
实际值会在第一次put(k,v)
重新计算。
1 | /** |
写一个测试 tableSizeFor
方法算出的结果
1 | public static void main(String[] args) { |
分析输出,这里输出的规律是,最小的2的幂1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
200:1
1:1
2:2
3:4
4:4
5:8
6:8
7:8
8:8
9:16
10:16
11:16
12:16
13:16
14:16
15:16
16:16
17:32
18:32
19:32
put(k,v)
如果是第一次调用会直接调用resize()
计算threshold
分配table
大小,方法在最后会判断size
大小是否大于 threshold
,如果插入元素大于threshold
则调用resize()
,然后重新计算 threshold
,调整table
的大小.阅读源码发现threshold
计算方式是table
大小乘负载系数 DEFAULT_LOAD_FACTOR
.也就是说如果new HashMap(8)
,在第一次put(k,v)
时会计算出threshold
为6(负载系数0.75
),在第6个参数put(k,v)
时,就会重新扩容。扩容的算法使用左移<<
算出结果等同*2
。如果想防止二次扩容可以使用实际参数数量 / 负载系数(默认0.75) + 1
.
1 | /** |
总结
如果想防止二次扩容可以使用此算法: 实际参数数量 / 负载系数(默认0.75) + 1
.