众所周知,ArrayList是Java中常用的集合类之一,它是基于数组实现的可变长容器,因此在添加元素时需要考虑到数组的扩容问题。下面我们来浅谈一下关于ArrayList的扩容问题。
-
初始容量:当创建ArrayList对象时,Java虚拟机会给该数组分配一个默认的初始容量。默认值为10。我们也可以在创建ArrayList时通过构造函数指定初始容量。
-
当数组被填满时,会执行扩容操作。扩容会创建一个新的数组,并将原始数组中的所有元素复制到新数组中。新数组的大小通常是原始大小的1.5倍。
-
扩容的时间复杂度为O(n),其中n为当前ArrayList的大小。这是由于在扩容过程中需要将原始数组中的所有元素复制到新数组中,这需要O(n)的时间复杂度。
-
如果我们知道ArrayList的最大元素数量,我们可以通过指定初始容量来避免在运行时进行扩容。这可以提高性能,因为扩容是一个耗时的操作。
下面是一个简单的示例程序,演示了ArrayList的扩容机制:
import java.util.ArrayList;
import java.util.List;
public class ArrayListExample {
public static void main(String[] args) {
// 创建一个初始容量为3的ArrayList对象
List<Integer> list = new ArrayList<>(3);
// 添加4个元素
list.add(1);
list.add(2);
list.add(3);
list.add(4);
// 打印ArrayList的大小和容量
System.out.println("ArrayList大小: " + list.size());
System.out.println("ArrayList容量: " + getCapacity(list));
// 添加第5个元素,触发扩容操作
list.add(5);
// 打印ArrayList的大小和容量
System.out.println("ArrayList大小: " + list.size());
System.out.println("ArrayList容量: " + getCapacity(list));
}
// 获取ArrayList的容量
private static int getCapacity(List<?> list) {
try {
java.lang.reflect.Field field = ArrayList.class.getDeclaredField("elementData");
field.setAccessible(true);
return ((Object[]) field.get(list)).length;
} catch (Exception e) {
return -1;
}
}
}
在上面的示例中,我们创建了一个初始容量为3的ArrayList对象,并添加了4个元素。在添加第5个元素时,触发了扩容操作。
在示例中,使用了反射来访问ArrayList内部的数组元素。这是因为ArrayList并没有提供直接获取容量的方法。