文章目录
ArrayList 的数据结构
ArrayList 底层的数据结构就是数组,数组元素类型为 Object 类型,即可以存放所有类型数据。对该类的实例的所有操作底层都是基于数组的。
实际大小:size
容量:CAPACITY
继承结构
- ArrayList 是直接继承自 AbstractList,为什么不是 List?
这里的设计思想:我们知道接口中的方法都是抽象的,而抽象类中可以有抽象方法,还可以有具体的方法。这里是让 AbstractList 实现接口中通用方法,而它具体的子类 ArrayList 可以拿到一些通用的方法外再自己实现一些特有方法。使得代码简洁。所以一般一个类上面还有一个抽象类应该都是这个作用。 - 实现 RandomAccess 接口:表明 ArrayList 支持固定时间随机访问。通过序号定位元素对象
- 实现 Cloneable 接口,可以调用 Objec.Clone() 方法
- 实现 java.io.Serializable:该类具有序列化功能
源码分析
域信息
// 版本号
private static final long serialVersionUID = 8683452581122892189L;
// 默认初始化容量为 10 (缺省容量)
private static final int DEFAULT_CAPACITY = 10;
// 指定 ArrayList 容量为 0 时,返回空数组 (空对象数组)
private static final Object[] EMPTY_ELEMENTDATA = {
};
// 当调用无参构造,返回的是该数组,刚创建一个 ArrayList 时,数据量为 0,
// 与前面区别在于此数组默认返回,而 EMPTY_ELEMENTDATA 是用户指定容量为 0 返回
// (缺省空对象数组)
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
};
// 保存数据的数组
transient Object[] elementData;
// 实际元素大小,默认为 0
private int size;
// 最大容量
// 分派给arrays的最大容量
// 为什么要减去8呢?因为某些VM会在数组中保留一些头字,尝试分配这个最大存储容量,
// 可能会导致array容量大于VM的limit,最终导致OutOfMemoryError。
// MAX.VALUE为0x7fffffff,转换成十进制就是2147483647,也就是数组的最大长度是2147483639;
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
构造方法
初始化一下储存数据的容器,其实本质上就是一个数组,在其中就叫elementData。
- 无参构造 ArrayList()
// ArrayList中储存数据的其实就是一个数组,这个数组就是elementData
public ArrayList() {
// 调用父类中的无参构造方法,父类中的是个空的构造方法
super();
// EMPTY_ELEMENTDATA:是个空的Object[]
// 这里将elementData初始化,而 elementData 也是 Object[]
// 空的 Object[] 会在第一次 add 时给默认容量 10
this.elementData = EMPTY_ELEMENTDATA;
}
- 有参构造有如下两个
// 构造一个指定容量为capacity的空ArrayList,带初始容量大小的有参构造
public ArrayList(int initialCapacity) {
super(); //父类中空的构造方法
//判断如果自定义大小的容量小于0,则非法数据异常
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
// 将自定义的容量大小当成初始化 elementData 的大小
this.elementData = new Object[initialCapacity];
}
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
//每个集合toarray()实现方法不一样,所以需要判断一下,如果不是Object[].class类
//型,那么就需要使用ArrayList中的方法去改造一下。
if (elementData.getClass() != Object[].class)
//copyOf(要复制的数组,要返回的副本的长度,要返回的副本的类)
elementData =