ArrayList 概述
ArrayList
实现了 List
接口,其实就是一个数组列表,不过作为 Java 的集合框架,它只能存储对象引用类型,也就是说当我们需要装载的数据是诸如 int
、float
等基本数据类型的时候,必须把它们转换成对应的包装类。
ArrayList
的底层实现是一个 Object
数组:
transient Object[] elementData;
既然它是基于数组实现的,数组在内存空间中是连续分配的,那必然查询速率非常快,不过当然也肯定逃不过增删效率低的缺陷。
另外,和 ArrayList
一样同样实现了 List
接口的、我们比较常用的还有 LinkedList
。LinkedList
比较特殊,它不仅实现了 List
接口,还实现了 Queue
接口,所以你可以看见 LinkedList
经常被当作队列使用:
Queue<Integer> queue = new LinkedList<>();
LinkedList
人如其名,它的底层自然是基于链表的,而且还是个双向链表。链表的特性和数组正好是反的,由于没有索引,所以查询效率低,但是增删速度快。
ArrayList 如何指定底层数组大小的
既然咱真正存储数据的地方是数组,那我们初始化 ArrayList
的时候自然要给数组分配一个大小,开辟一个内存空间。我们先来看看 ArrayList
的无参构造函数:
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
};
可以看到,它为底层的 Object
数组也就是 elementData 赋值了一个默认的空数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA
。也就是说,使用无参构造函数初始化 ArrayList
后,它当时的数组容量为 0 。
这给咱初始化一个容量为 0 的数组有啥用?啥也存不了啊?别急,如果使用了无参构造函数来初始化ArrayList
, 只有当我们真正对数据进行添加操作 add
时,才会给数组分配一个默认的初始容量DEFAULT_CAPACITY = 10
,源码如下:
public void add(int index, E element) {
rangeCheckForAdd(index);
// 第一步
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1, size - index);
elementData[index] =