ArrayList源码解析
类结构
类继承体系
- 继承自AbstractList(顶级为Collection接口)
- 实现了List接口,实现了集合运算、集合增删改查的方法
- 实现RandomAccess接口,这只是一个标志接口,里面没有方法,区别于LinkedList,表示ArrayList更适用于随机访问,即fori循环行性能比迭代器性能高
- 实现Cloneable接口,可以调用clone方法进行深拷贝
- 实现Serializable接口,可以使用ObjectInputStrem、ObjectReader等进行序列化与反序列化
核心属性
elementData是ArrayList底层的数据结构,即Object数组;transient关键字表示该变量无法被序列化,防止序列化破坏ArrayList的封装性
size是ArrayList对象的有效元素大小,当size增加到数组的容量时,将会触发扩容
这是ArrayList从AbstarctList继承来的属性,表示结构变化次数,每次扩容、删除等都会引起modCount的改变,它用于迭代器的快速失败,如果在迭代过程中出现了对ArrayList的修改导致modCount变化了,即结构发生变化,则迭代器会抛出Concurrent Modification Exception
ArrayList创建与基本使用
空参创建与首次扩容
通过空参构造器创建的ArrayList底层是一个空数组,在第一次添加元素时,这个常量将会被用于判断是否是空参构造的ArrayList,如果是空参构造的数组,在第一次添加元素进行扩容时,会被扩容为10
带参创建与扩容
传入指定容量
通过传入一个int类型可以指定底层数组的初始大小,现讨论传入0的特殊情况,这里底层同样会被初始化为空数组,但是区别于空参构造器,两者指向的并不是同一个对象,所以这里不会像空参构造一样在第一次扩容为10
传入已有集合参数
因为ArrayList底层使用的是Object数组,所以这里将数组转成Object类型
删除元素
根据索引删除
根据元素删除
根据索引区间删除
通过过滤器指定条件删除removeIf
修改元素
由此可见,ArrayList的set方法只能用来修改元素,不能用来增加元素,如果set方法传入的index在list长度之外,会在rangeCheck时报错IndexOutOfBoundsException
查询元素
ArrayList中常用方法
继承自List的集合处理方法(源码从上至下)
size和isEmpty
contains和indexOf
toArray
注意,这里的两个toArray方法不光实现了List接口还实现了AbstractCollection接口,可能有疑问实现的到底是哪个接口的方法,其实多虑了,这两个接口中任何一个类型的引用都可以传入ArrayList实例来调用这一段方法,下面这段代码佐证了这一点
public class Test {
public static void main(String[] args) throws Exception {
Method m = Class.forName("A").getDeclaredMethod("a");
Method m2 = Class.forName("B").getDeclaredMethod("a");
C c = new C();
m.invoke(c);
m2.invoke(c);
}
}
interface A{
void a();
}
interface B{
void a();
}
class C implements A,B{
@Override
public void a() {
System.out.println("a");
}
}
clear
addAll
removeAll和retainAll
replaceAll和sort
序列化方法
- 上面核心属性部分可以看到,elementData被transient修饰,是不能直接通过ObjectOutputStream序列化的,而ArrayList又继承了序列化方法,具体的序列化方式如下
- ArrayList继承了Serialziable接口,表示ArrayList是可序列化的,它内部定义了readObject和writeObject方法,在序列化时,如果对象定义了这两个方法,则JVM会调用这两个方法来进行用户自定义的序列化和反序列化,没有定义则使用则默认调用是 ObjectOutputStream 的 defaultWriteObject 方法以及 ObjectInputStream 的 defaultReadObject 方法
其他方法
修剪集合大小trimToSize
clone方法
forEach方法
内部类
迭代器
ArrayList中定义了两个内部迭代器类:Itr、ListItr,其中Itr实现了Iterator接口,ListItr是Itr的子类
Itr
属性
构造器
方法
ListItr
ListItr是Itr的优化版本
构造器
方法
获取迭代器的方法
子视图
ArrayList中还有一个内部类SubList,用于从ArrayList中截取部分子视图
属性
子视图的方法和ArrayList基本一致,不做过多重复的分析,子视图的每一次操作都是利用ArrayList.this.elementData进行的,所以会直接修改ArrayList
获取子视图的方法
ArrayListSpliterator
ArrayListSpliterator是1.8加入的分割迭代器,相较于普通的Iterator迭代器,它的资源消耗更少,不需要next和hasNex配合,一个tryAdvance操作就可以完成迭代,而且分割迭代器还可以进行分区迭代
属性
构造器
方法