ArrayList是我们经常使用到的集合。来阅读一下它的源码。
属性值
serialVersionUID--序列化版本号,用于辨识反序列化得到的对象和本身是不是同一个类的实例对象。
DEFAULT_CAPACITY 默认初始化容量,如果空元素集合为DEFAULTCAPACITY_EMPTY_ELEMENTDATA,则按照这个值来扩容。
EMPTY_ELEMENTDATA和DEFAULTCAPACITY_EMPTY_ELEMENTDATA都是静态的空数组,用于区分第一次扩容的大小,如果是EMPTY_ELEMENTDATA,就按照需要的容量来扩容,如果是DEFAULTCAPACITY_EMPTY_ELEMENTDATA,就按照10和需要的容量之间的较大值来扩容。
elementData--用于存放数据的元素数组。
size--集合中元素的数量。
构造方法
一个无参构造,将元素数组elementData赋值为DEFAULTCAPACITY_EMPTY_ELEMENTDATA。
一个需要int值的有参构造,int值为规定的初始容量,如果initialCapacity<0报错,如果initialCapacity为0,将elementData赋值为EMPTY_ELEMENTDATA,initialCapacity>0则新建一个指定大小的数组给elementData。
一个需要传入一个Collection集合的有参构造,将传入集合的值复制到本集合中,如果传入集合为null就将elementData赋值为EMPTY_ELEMENTDATA。
扩容相关的方法
ensureCapacity中查看当前elementData是不是DEFAULTCAPACITY_EMPTY_ELEMENTDATA,如果是,则将下一次扩容值置为10,否则置为0。如果需要的容量大于下一次扩容值,就按照需要的容量扩容。
calculateCapacity中如果当前elementData是DEFAULTCAPACITY_EMPTY_ELEMENTDATA就返回10和需要容量的较大值。否则返回需要的容量。
ensureExplicitCapacity中会修改modCount,如果需要的容量大于当前容量,调用grow方法进行扩容。
grow中将elementData扩容1.5倍。
获取下标的方法
indexOf从前向后遍历,lastIndexOf从后向前遍历,找到匹配的值就返回下标,没有找到就返回-1。
克隆方法clone()
是一个浅拷贝,创建了一个新的数组,但是新数组中的元素是从原数组中直接引用过来的。
get()相关方法
elemetData(int index) 方法中返回了elementData元素数组的第index个元素并进行了强制类型转换。(elementData是一个Object[]数组)。
get()方法中校验了下标合法后就返回elemetData(index)。
set()方法
先保存旧值,然后覆盖旧值,最后将保存的旧值返回。
add()相关方法
没有指定下标的add方法,先对elementData元素数组扩容,然后直接将传入的值添加到末尾,然后对size加1。
指定了下标的add方法,先检查下标是否合法,然后对元素数组扩容,移动index位置即之后的元素,然后将传入的元素赋给index位置,再对size+1。
未指定下标的addAll() 方法,将传入集合的内容添加到末尾。
指定了下标的addAll()方法,将数组从指定下标开始向后移动传入集合的长度,然后将传入结合的元素添加到空出来的位置。
remove()相关方法
按下标删除元素,将需要删除位置之后的元素向前移动,覆盖掉需要删除的元素即可。
按元素删除,找到需要删除的第一个元素,然后将之后的元素向前移动覆盖。
范围删除,将范围末尾之后的元素覆盖范围开始。
批量删除和批量保留
都是校验传入集合后,调用批量删除batchRemove()方法。
将需要保留的元素移动到数组开始,将 之后的元素置空。
迭代器
Itr迭代器
Itr实现了迭代器接口,有三个参数
cursor---下一个元素的索引
lastRet---最后一次访问元素的索引
expectedHodCount--暂存当前modCount
hasNext和next方法
hasNext就是判断下一个元素是不是数组末尾。
next会先检查modCount,如果不匹配就抛错,匹配了才返回下一个值,并修改cursor和lastRet。
remove()方法
是通过调用ArrayList的remove()方法实现的,但是在调用完后会修改保存的expectedHodCount,所以不会抛出ConcurrentModificationException异常。
forEachRemaining()方法
遍历剩余的元素执行传入的操作。
ListItr迭代器
继承自Itr迭代器类。
三个方法
set和add是通过ArrayList的set和add实现的,修改完成后会修改保存下来的expectedHodCount,所以不会抛出ConcurrentModificationException异常。