ArrayList源码解析
简介
特点:ArrayList是List接口的主要实现类,它存储有序的,可重复的数据。
优缺点:ArrayList线程不安全,但其查询、修改数据的效率高。
底层原理:ArrayList底层是基于数组来实现的。
Arraylist的继承与实现
ArrayList的类图(该图由Idea自动生成)
从上图可知,ArrayList继承了AbstractList,实现了Serializable、RandomAccess、Cloneable、List。
功能:
- 继承AbstractList类,实现了List接口。它是一个抽象类,实现了 List 的一些位置相关操作(比如 get,set,add,remove),是第一个实现随机访问方法的集合类,但不支持添加和替换。
- 实现Cloneable接口,重写了函数clone(),可以被克隆。
- 实现RandomAccess接口,提供了随机访问功能。
- 实现了Serializable接口,因此,ArrayList支持序列化,可以将对象转换为可保持或可传输的过程。
源码解析
本文将从ArrayList使用的角度解析源码
ArrayList属性
在阅读源码前,我们需要先理解一些ArrayList属性代表的含义
// 数组默认的初始容量为10
private static final int DEFAULT_CAPACITY = 10;
// 空的Object数组
private static final Object[] EMPTY_ELEMENTDATA = {
};
// 空的Object数组,将其与上面的区分开来,EMPTY_ELEMENTDATA用于有参构造函数且参数为0时,而DEFAULTCAPACITY_EMPTY_ELEMENTDATA用于无参构造函数。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
};
// 集合中存放数据的对象,ArrayList的核心
transient Object[] elementData;
// 集合内数据的大小,size初始为0
private int size;
// modCount继承于AbstractList,用于记录数组的添加、删除操作次数
创建ArrayList对象
-
使用无参构造函数创建对象
ArrayList arr = new ArrayList();
在Idea中使用Ctrl+鼠标左键单击,可以进入ArrayList.java中查看源码。
// 可以看出,创建了一个elementData的长度为0的ArrayList对象 public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
-
使用有参构造函数创建对象,参数的类型为int。
// 创建一个长度为initialCapacity的elementData数组 public ArrayList(int initialCapacity) { // 如果初始容量长度大于0,则从新创建一个Object数组 if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; // 否则如果初始容量为0,则将EMPTY_ELEMENTDATA的地址赋给elementData。 } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { // 否则抛出异常 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
-
使用有参构造函数创建对象,参数的类型为Collection。
// 使用这种方式创建ArrayList对象,会将Collection对象转为Object数组,然后将其拷贝给elementData数组 public ArrayList(Collection<? extends E> c) { // 将Collection对象转为数组 Object[] a = c.toArray(); // 将b数组的长度赋值给size,判断其是否不等于0 if ((size = a.length) != 0) { if (c.getClass() == ArrayList.class) { // 将a的地址赋给elementData elementData =</