ArrayList 源码分析

ArrayList继承了AbstractList,实现了List接口,还有RandomAccess,Cloneable,Serializable三个标识接口。非同步。

属性

主要维护了两个Object数组,一个static final 的空数组用来表示空List,一个transient的数组用于存取数据。

构造器

一个利用空数组直接构造空List,一个从容量构造,一个从另外的Collection构造(由数组的复制实现)。

容量保证

List提供了指定最小容量(设为C)的方法ensureCapacity,实现是先比较C与默认容量,可以的话就用默认容量,不行就在原有容量上增加0.5倍,依然不满足就直接使用C的大小,还不行就使用Integer的最大数组值(考虑到某些虚拟机会在数组中添加头部字节,占用一些空间,所以尽量不直接使用int最大值),这样还不行就直接使用int最大值。

同时在这个不断试探的过程中:1、伴随着各个条件下的参数检查,以确保不会溢出。2、modCount(结构性修改次数,主要用于Iterator的fail-fast机制)标识位值增加

add(e)

先保证容量,再将元素引用存入数组。

add(index,e)

先检查index合法性,再保证容量,再进行数组的插入(先移后插或者直接插入,具体要看System.ArrayCopy native方法的具体实现。)

addAll(Collection c)

先将c转为数组,再保证List容量,再进行System.ArrayCopy

addAll(index,c)

思路同add(index,e)

trimToSize()

节约内存

remove(index)

index合法性检查,modCount++,再进行数组删除(先删再移/直接删,System.ArrayCopy),最后将数组末尾值置为null

remove(object)

NPE检查,遍历数组查找其index,modCount++,并删除(System.ArrayCopy),最后将数组末尾值置为null

chear()

modCount++,数组所有位置赋值为null并将size归零

removeRange(index1,index2)

思路大致同remove(index)

removeAll(collection c)和retainAll(collection c)

两个方法都由private方法 batchRemove(collection c,boolean complement)实现,其思路是挨个比较c和本来list中的元素是否相等,然后将需要保留的元素(removeAll将保留除c以外的,retainAll将保留c中所有)逐个移到list数组前端,然后将其余的元素置为null。该方法巧妙在用一个boolean变量,使一段代码可以重复用于两种截然相反的方法。

toArray()

调用Arrays类copyof静态方法,该方法是泛型方法,思路是先获取list中数组持有对象的运行时类型,然后新建一个该类型的数组,然后调用System.ArrayCopy()。返回的是Object类型的数组,但是数组里保存的是实际类型。

List<String> list = new ArrayList<String>();
list.add("sjsh");
list.add("dafjdslj");
Object[] a = list.toArray();
System.out.println(a[0].getClass());

输出 class java.lang.String

toArray(T[] a)

主要将list转存到特定类型的数组a中。
如果a的长度小于list的size,则先获取a的运行时类型,然后通过Arrays.copyof()方法创建新的a类型的size大小的数组并返回。
如果a的长度足够大装的下list的所有元素,则直接调用System.arrayCopy()方法将list数组转存至a数组,如果运行时类型不相同的话会抛ArrayStoreException。如果a数组的长度大于list的size,则将a[size]位置为null,用于在已知数组不含null元素的情况下判断数组的实际长度。

这里说一下Arrays.copyOf()方法和System.arraycopy()方法的关系。
1、Arrays.copyOf()中数组复制调用的就是System.arraycopy()。
2、Arrays.copyOf()是首先获取泛型入参的运行时类型,再新建一个该类型的数组,然后调用System.arraycopy()进行复制。System.arraycopy()是直接赋值给入参数组。

Set(int index,E element)

先进行index合法性检查,再进行E类型元素赋值操作。

size()

isEmpty()

indexOf(Object o)

遍历数组,如果两个对象引用相同,返回数组中该引用的index,没有找到则返回-1

lastIndexOf(Object o)

反向遍历

contains(Object o)

检查indexOf方法的返回值是否大于等于0

get(int index)

index合法性检查,通过数组索引返回对应值

listIterator()

通过内部私有类,返回List迭代器(正反向都可以)

listIterator(index)

index合法性检查,返回List迭代器

iterator()

返回常规迭代器,带有fail-fast机制。

fail-fast机制:迭代器生成时获取List属性中的modCount数值并赋值给迭代器属性中的expectedModCount,每次执行next和remove方法时再将expectedModCount与modCount比较,如不同则抛ConcurrentModificationException

subList(int fromIndex,int toIndex)

先进行index合法性检查,再通过私有内部类返回sublist(原list的视图)。

该视图由原list支持,并获取原list的modCount数值,所有非结构化修改都会直接相互反映给对方。视图的的所有方法无一例外在执行时都会先检查是否有结构化修改发生,如果有将抛ConcurrentModificationException。

序列化

writeObject

readObject

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值