一、初始容量的确定:

1、调用无参构造:ArrayList()

会使用长度为0的数组作为初始容量

2、调用带参构造:ArrayList(int initialCapacity)

会使用指定容量的数组作为初始容量

3、调用带集合参数构造:public ArrayList(Collection<?extends E>c)

会使用c(集合)的大小作为数组的初始容量

二、add和addAll方法的扩容规则:

1、调用add方法的扩容规则:

add(Object o)首次扩容为10,再次扩容为上次容量的1.5倍。

这是针对初始长度为0的数组来说的,如果初始数值不是0,那么就是上次容量1.5倍。

调用无参的ArrayList数组,初始容量是0而不是10。

第一次扩容是从0到10,第二次扩容是上一次容量的1.5倍(10~15),第三次是15右移一位,等于除以2,得到7,再和原容量相加15+7=22,15到22就是第三次的范围。

以后的扩容规则都是上一层容量的1.5倍。

20次:[0,10,15,22,33,49,73,109,163,244,366,549,823,1234,1851,2776,4164,6246,9369,14053,21079]

2、调用addAll方法的扩容规则:

addAll(Collection c)没有元素时,扩容为Math.max(10,实际元素个数),
有元素时为Math.max(原容量1.5倍,实际元素个数)。

对于addAll方法,如果集合中原来没有元素,则下一次在10和实际元素个数中找一个最大值;
如果集合中已经有元素了,就是下一次扩容的1.5倍容量和实际元素个数选一个最大值,作为下一次的扩容容量。

一次添加一个集合,集合里可能有多个元素,不够用时也会触发扩容。

第一次的集合如果小于10,比如3个元素,就会扩容成10,如果大于10,比如元素是11个,则会扩容成11,而不是15(一次扩容能解决的,就不扩容多次,从0跳到11,而不是从0跳到10再跳到15)。

当你原始的容量不够时,他就会在下一次扩容的容量的大小,和我们元素个数 二者之间找一个较大值,作为下一次的容量。
也就是原来一个集合里有10个元素,此时容量10,下一次的集合里来了3个元素,此时容量在下一次扩容点15和元素总数13中选一个大的,就是15。

addAll方法的扩容是在下一次扩容的容量和元素总个数二者之间选择一个较大值,作为下一次扩容的容量。

一句话:
add(Object o)首次扩容为10,再次扩容为上次容量的1.5倍。
addAll(Collection c)没有元素时,扩容为Math.max(10,实际元素个数),有元素时为Math.max(原容量1.5倍,实际元素个数)。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐