Java专栏:以动画的方式带你深入理解Java源码ArrayList!!!
大家好,我是老黑[1]。
今天我们来研究研究Java集合ArrayList的源码,废话不多说,开搞。
先抛出几个问题:
你是否知道ArrayList的存储原理? 你是否知道ArrayList的扩容原理? 你知道ArrayList什么时候扩容吗? 你知道ArrayList是线程安全的吗? 你知道ArrayList与LinkedList的区别吗?
(答案与ArrayList生命周期动画放在文末~)
再预览一下本文大纲:

ArrayList概述
ArrayList是Java语言中最常见的集合工具类之一,它继承AbstractList,实现了以下接口:
List(列表)
RandomAccess(顺序访问)
Cloneable(可克隆)
Serializable(可序列化)
从它的继承与实现来看,ArrayList是一个可克隆,可序列化,可顺序访问的列表。
ArrayList的存储原理
在ArrayList中,内部拥有4个属性:

从上图发现,ArrayList的实现原理内部其实是一个对象数组:Object[]
,然后还有一个属性size
用来表示链表的实际长度。

源码分析
增
add(E object)


add(int index, E object)


请问:这个方法是线程安全的吗?
我们再看一个动画演示:

所以,add(int index, E object)
不是线程安全的。
删
remove(int index)

remove(Object o)

改
set(int index, E object)

修改与删除不同,修改没有类似CAS(比较并且交换)的API。
在这里多提一嘴,我们要知道,一个列表存放的到底是什么?
没错,存放的是对象的地址,而不是真正的对象,下面再来看一下动画演示如何修改的:

查
查询比较简单,直接根据下标获取数据即可。

迭代器
ArrayList.Itr迭代器

迭代器的这些方法其实都是我们经常会使用到的,hasNext
、next
、remove
等等。


小结:
使用迭代器后,在迭代器外部最好是不要操作列表,否则在后续使用这个迭代器时很有可能将抛出异常; 使用next之前一般都会使用hasNext进行判断; 使用remove之前必须使用next方法; 使用remove方法后迭代器内部的expectedModCount会同步更新,所以在迭代器内部remove是允许的; remove方法不允许连续使用两次,因为在第一次使用后lastRet就会置为-1,下次remove时判断lastRet<0则抛出IllegalStateException。
ArrayList.ListItr迭代器
ListItr是继承了Itr的,所以Itr的所有功能在ListItr都有。
ListItr与Itr的区别是:
Itr只能从前往后迭代,并且是不允许查找上一个数据;
而ListItr则允许从前往后和从后往前两种迭代方向,同时也允许查找上一个数据,并且也允许从中间某一个位置开始遍历。
遍历方式
准备
List