HashMap和ConcurrentHash进行初始化时inittialCapacity的区别

问题描述:我们在new HashMap(16)和new ConcurrentHashMap(16)时,这两个16有什么区别呢?

结论:

HashMap中initialCapacity指数组大小,比如指定inittialCapacity为16,那么初始化创建的数组大小就是16;

ConcurrentHashMap中inittialCapacity指ConcurrentHashMap的容量,而不是数组大小。比如,如果指定inittialCapacity为16,负载因子为0.75,那么初始化创建的数组大小为32(inittialCapacity/0.75+1,在通过tableSizeFor()取不小于这个数的2次方)。

所以感觉ConcurrentHashMap的inittialCapacity更符合我们平时所说的初始容量的语义。

代码分析:

HashMap:

HashMap和ConcurrentHash进行初始化时inittialCapacity的区别_第1张图片

可以看到,HashMap经过一系列的边界检查后,通过tabeSizeFor(initialCapacity)这个方法进行赋值给this.threshold。

先说tabeSezeFor(inittialCapacity)方法,这个方法主要是返回一个不小于输入值的最小2次方整数。有点拗口,简单说就是如果输入15,则不小于15的最小2次方整数就是16,如果输入16,则返回16。

再说this.threshold,这个字段其实是用于扩容判断,比如每次添加元素要判断HashMap中元素是否超过threshold,如果超过,则要进行扩容。而HashMap中没有专门的字段保存初始容量,所以将通过tabeSizeFor(inittialCapacity)计算的初始容量保存在了this.threshold。

HashMap的初始化是采取懒初始化的方式,就是说我们执行new HashTable(16),实际上这个时候没有进行内部数组的初始化,而是在我们插入元素的时候才new数组。

所以说当我们往HashTalbe中插入元素时,HashTable会将this.threshold的值取出,初始化数组。因此,HashTable中的initialCapacity其实是指HashTable中数组的大小。

ConcurrentHashMap:

HashMap和ConcurrentHash进行初始化时inittialCapacity的区别_第2张图片

ConcurrentHashMap进行了边界检查后,将通过tableSizeFor(inittialCapacity)取不小于inittialCapacity/loadFactor+1的最小2次方整数。比如inittialCapacity为16,loadFactor为0.75,最后通过tableSizeFor()运算得32。最后将这个数存入this.sizeCtl。ConcurrentHashMap也是在插入的时候才取出这个数进行数组初始化。

所以,ConcurrentHashMap中的inittialCapacity是指HashMap的容量,不是指的数组大小,实际初始化的数组要比inittialCapacity大。

你可能感兴趣的:(java集合框架)