引:大家在集合框架中用的最多一定是ArrayList吧,今天我们就来一探究竟!
详细注释:源码分析地址
概览
ArrayList是基于可变数组实现了,允许包括 null 在内的所有元素。
每个 ArrayList 实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长。
在添加大量元素前,应用程序可以使用 ensureCapacity 操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。
注意: 此实现不是同步的。如果多个线程同时访问一个 ArrayList 实例,而其中至少一个线程从结构上修改了列表,那么它必须保持外部同步。(结构上的修改是指任何添加或删除一个或多个元素的操作,或者显式调整底层数组的大小;仅仅设置元素的值不是结构上的修改。)这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使用 Collections.synchronizedList 方法将该列表“包装”起来。这最好在创建时完成,以防止意外对列表进行不同步的访问。
此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:在创建迭代器之后,除非通过迭代器自身的 remove 或 add 方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出 ConcurrentModificationException。
ArrayList从类 java.util.AbstractList 继承了字段 modCount,在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了需要抛出 ConcurrentModificationException。
构造
1 | // 默认数组初始大小为10 |
增
1 | // 新增元素 |
删
删除需要将 index+1 后面的元素都复制到 index 位置上,该操作的时间复杂度为 O(N),所以ArrayList 删除元素的代价是非常高的。
1 | public E remove(int index) { |
改
1 | public E set(int index, E element) { |
查
1 | public E get(int index) { |
序列化
ArrayList 基于数组实现,并且具有动态扩容特性,因此保存元素的数组不一定都会被使用,那么就没必要全部进行序列化。
1 | // 保存元素的数组 elementData 使用 transient 修饰,该关键字声明数组默认不会被序列化 |