ArrayList是我们日常开发中最常用的集合类甚至没有之一,了解其底层源码非常重要,以下源码基于
jdk1.8.0_144版本
一、ArrayList的数据结构
集合框架数据结构是其灵魂,理解数据结构才能更好理解ArrayList的实现思路。
ArrayList的数据结构如下:
ArrayList其底层是一个动态数组,存储的元素是所有对象即Object,下面看ArrayList是如何实现动态数组的。
二、ArrayList的继承体系
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
ArrayList实现了List接口、RandomAccess(可随机访问)、Cloneable(可拷贝)、Serializable(可序列化)。
继承了AbstractList
2.1 实现RandomAccess接口的作用:
RandomAccess是List 实现所使用的标记接口,用来表明其支持快速(通常是固定时间)随机访问。此接口的主要目的是允许一般的算法更改其行为,从而在将其应用到随机或连续访问列表时能提供良好的性能。
将操作随机访问列表的最佳算法(如 ArrayList)应用到连续访问列表(如 LinkedList)时,可产生二次项的行为。如果将某个算法应用到连续访问列表,那么在应用可能提供较差性能的算法前,鼓励使用一般的列表算法检查给定列表是否为此接口的一个 instanceof,如果需要保证可接受的性能,还可以更改其行为。
现在已经认识到,随机和连续访问之间的区别通常是模糊的。例如,如果列表很大时,某些 List 实现提供渐进的线性访问时间,但实际上是固定的访问时间。这样的 List 实现通常应该实现此接口。实际经验证明,如果是下列情况,则 List 实现应该实现此接口,即对于典型的类实例而言,此循环:
for (int i=0, n=list.size(); i < n; i++){
list.get(i);
}
的运行速度要快于以下循环:
for (Iterator i=list.iterator(); i.hasNext(); ){
i.next();
}
2.2 实现Cloneable接口的作用:
此类实现了 Cloneable
接口,以指示 Object.clone()
方法可以合法地对该类实例进行按字段复制。
如果在没有实现 Cloneable
接口的实例上调用 Object 的 clone 方法,则会导致抛出 CloneNotSupportedException
异常。
按照惯例,实现此接口的类应该使用公共方法重写 Object.clone(它是受保护的)。请参阅 Object.clone()
,以获得有关重写此方法的详细信息。
注意,此接口不 包含 clone 方法。因此,因为某个对象实现了此接口就克隆它是不可能的。即使 clone 方法是反射性调用的,也无法保证它将获得成功。
2.3实现Serializable接口的作用:
类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
三、ArrayList的field
/**
*
* 为保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化
* 类必须声明一个明确的 serialVersionUID 值。
* 还强烈建议使用 private 修饰符显示声明 serialVersionUID(如果可能),
* 原因是这种声明仅应用于直接声明
* 类 -- serialVersionUID 字段作为继承成员没有用处
*
*/
private static final long serialVersionUID = 8683452581122892189L;
/**
* 默认初始容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 空的实例.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 元素数组
transient Object[] elementData; // non-private to simplify nested class access
//元素的个数
private int size;
//分配数组的最大值
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
elementData,类型为Object[]的数组,用于存放实际元素,并且被标记为transient,也就意味着在序列化的时候,此字段是不会被序列化的
protected transient int modCount = 0;
modCount 是从其父类继承来的,已从结构上修改 此列表的次数。
四、ArrayList的构造函数
//构造一个空的list其size为DEFAULT_CAPACITY 10
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//构造一个空的list根据指定的size
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
thr