ArrayList源码解析

ArrayList源码解析
jwang源码分析步骤
- 看继承结构:看这个类的层次结构,处于一个什么位置,可以在自己心里有个大概的了解。
- 看构造方法:在构造方法中,看做了哪些事情,跟踪方法中里面的方法。
- 看常用的方法:跟构造方法一样,这个方法实现功能是如何实现的
关系依赖
类继承及实现接口
public class ArrayList<E> |
AbstractList: 该类提供了List接口的骨架实现,以最小化实现这个由“随机访问”数据存储(如数组)支持的接口所需的工作。对于顺序访问数据(比如链表),应该优先使用AbstractSequentialList而不是这个类。要实现不可修改的列表,程序员只需要扩展这个类并提供get(int)和size()方法的实现。要实现一个可修改的列表,程序员还必须重写set(int, E)方法(否则将抛出UnsupportedOperationException)。如果列表是可变大小的,程序员还必须重写add(int, E)和remove(int)方法。与其他抽象集合实现不同,程序员不需要提供迭代器实现;迭代器和列表迭代器由这个类实现,按照collection接口规范中的建议,程序员通常应该提供一个void(没有参数)和集合构造函数。
List:List类的顶层父类,所有相关list有序集合都会实现该类,除了在Collection接口中指定的规定之外,List接口对迭代器(在调用者不知道实现的情况下,对列表中的元素进行迭代通常比对其进行索引要好。)、add、remove、equals和hashCode方法进行了额外的规定
RandomAccess:表明它们支持快速(通常是常量时间)随机访问
Clonewable:一个类实现了Cloneable接口来指示Object.clone()方法,该方法对该类的实例进行字段对字段的复制是合法的。在一个没有实现Cloneable接口的实例上调用Object的克隆方法会导致抛出CloneNotSupportedException异常。
属性
private static final int DEFAULT_CAPACITY = 10; 默认初始化容量 |
构造函数
ArrayList(int initialCapacity):
构造一个有指定初始化容量的空集合 initialCapacity = 0 ?elementData=EMPTY_ELEMENTDATA:new Object[initialCapacity]ArrayList():构造一个初始化容量为10的空list,elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATAArrayList(Collection<? extends E> c):构造一个包含指定集合元素的列表,按照集合迭代器返回元素的顺序。c不能为null,使用elementData = c.toArray().length!=0?Arrays.copyOf():EMPTY_ELEMENTDATA
方法
增加元素的方法
arrayList.add( E element); |
public boolean add(E e) { |
private void ensureCapacityInternal(int minCapacity) { |
- 判断当前是否是使用默认的构造函数初始化,如果是设置最小的容量为默认容量10,即默认的elementData的大小为10(这里是有一个容器的概念,当前容器的大小一般是大于当前ArrayList的元素个数大小的)
private void ensureExplicitCapacity(int minCapacity) { |
- modCount字段是用来记录修改过扩容的次数,调用ensureExplicitCapacity()方法意味着确定修改容器的大小,即确认扩容
private void grow(int minCapacity) { |
- 一般默认是扩容1.5倍,当时当发现还是不能满足的话,则使用size+1之后的元素个数,如果发现扩容之后的值大于我们规定的最大值,则判断size+1的值是否大于MAX_ARRAY_SIZE的值,大于则取值MAX_VALUE,反之则MAX_ARRAY_SIZE,也就数说容器最大的数量为MAX_VALUE
public void add(int index, E element) { |
删除元素的方法
arrayList.remove(Object o); |
public boolean remove(Object o) { |
public E remove(int index) { |
public boolean removeAll(Collection<?> c) { |
|
定义局部变量elementData、r、w、modified elementData用来重新指向成员变量elementData,用来存储最终过滤后的元素,w用来纪录过滤之后集合中元素的个数,modified用来返回这次是否有修改集合中的元素
for循环遍历原有的elementData数组,发现如果不是要移除的元素,则重新存储在elementData,且w自增
如果出现异常,则会导致 r !=size , 则将出现异常处后面的数据全部复制覆盖到数组里。
判断如果w!=size,则表明原先elementData数组中有元素被移除了,然后将数组尾端size-w个元素置空,等待gc回收。再修改modCount的值,在修改当前数组大小size的值
修改元素的方法
arrayList.set(int index, E element) |
查询元素的方法
arrayList.get(int index); |
判断是否存在某个元素
arrayList.contains(Object o); |
public boolean contains(Object o) { |
- 不管是contains方法还是lastIndexOf方法,其实就是进行for循环,如果找到该元素则记录下当前元素下标,如果没找到则返回-1
总结
- arrayList可以存放null。
- arrayList本质上就是一个elementData数组。
- arrayList区别于数组的地方在于能够自动扩展大小,其中关键的方法就是gorw()方法。
- arrayList中removeAll(collection c)和clear()的区别就是removeAll可以删除批量指定的元素,而clear是全是删除集合中的元素。
- arrayList由于本质是数组,所以它在数据的查询方面会很快,而在插入删除这些方面,性能下降很多,有移动很多数据才能达到应有的效果
- arrayList实现了RandomAccess,所以在遍历它的时候推荐使用for循环。








