指定initialCapacity参数的ArrayList构造方法有什么作用?
ArrayList(int initialCapacity)构造方法问题解答 核心概念前置说明
要搞懂这个问题,首先要区分ArrayList的两个完全不同的属性:
- 容量(capacity):ArrayList底层存储元素的数组的实际长度,属于内部实现参数,不会对外暴露
- 大小(size):ArrayList中实际存储的有效元素数量,是对外公开的列表长度,调用
size()方法返回的就是这个值
构造方法的作用
public ArrayList(int initialCapacity)的作用非常明确:初始化时提前将底层存储数组的长度设置为你指定的initialCapacity值,不会使用默认的初始容量规则(JDK8及之后默认无参构造的ArrayList初始容量为0,第一次添加元素时才会扩容到10)。
为什么访问小于初始容量的下标还会抛异常?
你调用get()、set()等方法访问下标时,Java判断下标是否合法的依据是size,不是容量。
举个例子:你执行ArrayList<Integer> list = new ArrayList<>(10);时,底层数组长度已经是10了,但你还没有添加任何元素,此时list.size()返回的是0,你哪怕访问下标0,都会因为下标 >= size触发IndexOutOfBoundsException,这是符合设计预期的。初始容量只是预分配了底层存储空间,不会凭空给列表生成占位元素,自然也不会改变列表的有效长度。
设置初始容量的实际意义
初始容量的核心作用是减少扩容带来的性能开销。
ArrayList的扩容逻辑是:每次添加元素时如果发现size == capacity,就会自动创建一个长度为原容量1.5倍的新数组,把原数组的所有元素复制到新数组中,再回收旧数组。如果元素数量很多,这个反复扩容、复制数组的过程会浪费大量性能。
举个实际场景对比:你需要往列表里插入10000条数据
- 使用默认无参构造:需要经历7次扩容,累计要复制近20000次元素,还会产生多个临时的旧数组对象,增加GC压力
- 使用
new ArrayList(10000)构造:全程不会触发任何扩容,插入操作的耗时能降低30%以上,元素越多性能提升越明显
当然初始容量也不是设置得越大越好,如果你只需要存10个元素却设置了10000的初始容量,反而会浪费不必要的内存空间,最好是根据你预估的实际元素数量来设置。
内容的提问来源于stack exchange,提问作者grabeqc
相关产品推荐
相关产品推荐

