ArrayList 源码解析

在平时Java,存储数据需要用到列表,而大多时候都能用到ArrayList,比如Mybatis查询数据列表,返回列表都是ArrayList,很多数据的存放也用到了ArrayList。
jdk 版本: 1.8
ArrayList 是基于大小可变的数组实现,并允许添加null值, 根据下标就能数据查询快。数组一旦初始化就确定好了大小,如果需要添加数据,就需要做数据的复制,这些操作比较耗时。
数组拷贝
ArrayList数组的扩容、添加和删除需要用到数组的拷贝,主要用到了以下两个方法:
System.arraycopyArrays.copyOf
System.arraycopy
System.arraycopy() 是Java的原生的静态方法,该方法将源数组元素拷贝到目标数组中去。
参数详解:
src 源数组
srcPos 源数组拷贝的起始索引
dest 目标数组
destPos 拷贝到目标数组的起始索引
length 拷贝元素的个数将
src源数组,起始索引为srcPos,个数为length,复制到起始索引为destPos的dest目标数组。
比如:
输出:
Arrays.copyOf
Arrays.copyOf本质也是调用System.arraycopy方法:
首先创建一个新的数组copy,将original数组全部复制给copy数组。
主要字段:
ArrayList是基于数组的一个实现,elementData就是底层的数组。size是记录数组的个数。
构造方法
ArrayList()
无参构造方法,创建数据直接赋值一个空数组。
ArrayList(int initialCapacity)
赋一个初始化容量initialCapacity:
初始化容量
initialCapacity大于零,新建长度initialCapacity的数组。初始化容量
initialCapacity等于零,新建一个空数组。
添加数据
添加数据有两个方法:
add(E e) 直接添加在数组尾部。
add(int index, E element) 根据下标添加数据。
add(E e)
在列表尾部添加数据:
ensureCapacityInternal 判断添加数据后的容量是否足够,如果不够,做扩容操作。
ensureCapacityInternal 作用是判断容量当前容量是否足够存放新的数据,如果不够就做扩容操作。
calculateCapacity计算容量,如果数组为null,返回minCapacity和10的最大值,否则返回minCapacity。这个方法就是返回数组的大小。
调用无参构造方法
ArrayList(),再调用add()方法,首先数组容量会变成10。这也是为什么无参构造方法ArrayList()上面有会有注解Constructs an empty list with an initial capacity of ten.
ensureExplicitCapacity 判断需要的容量minCapacity大于当前数组的长度elementData.length,将会做扩容处理,也是调用grow方法:
group 主要做了两件事:
长度扩大到原来的 1.5 倍
拷贝数组到新长度的数组
做完判断是否要做扩容之后,直接在 size 位置上赋值要添加的元素,然后 size 再自增。
add(E e)流程总结
判断数据容量是否足够,如果是空数组,返回
10,其他容量返回当前数组size + 1。返回容量和当前数组长度对比,小于做扩容处理。
扩容长度为原来长度的
1.5倍,将数组赋值给长度为原来数组1.5倍的新数组。在数组的最末尾
size赋值。
add(int index, E element)
此添加数据是在指定的下标添加数据。
add(int index, E element) 在index下标添加数据,
首先判断
index是否在0 ~size之间。判断是否要扩容,需要扩容,进行
1.5倍扩容。数据迁移,把
index以后的数据全部往后移动一位。赋值
index下标数据。
获取数据
获取数据只有通过数组下标获取数据 get(int index):
这里获取数据就比较简单:
检查下标是否超过数组范围。
通过下标访问数据。
删除数据
remove(Object o)
删除列表中第一个匹配的元素:
判断要删除数据是否为null:
为空,判断
elementData[index]是否为空。不为空,判断元素
equals是否匹配elementData[index]。
上面判断都为true时,调用fastRemove方法:
移动数组数据,index+1 以及之后的数据往前移动一位,最后一位size-1赋值为null。
remove(int index)
根据index下标删除数据。
总结
数组的扩容、添加和删除都需要用到
System.arraycopy方法,System.arraycopy是将src源数组,起始索引为srcPos,个数为length,复制到起始索引为destPos的dest目标数组。ArrayList主要是基于Object[] elementData动态数组实现。调用构造方法,无参的就赋值一个空数组,有初始容量的就赋值一个初始容量。
add添加数组首先判断是否需要扩容,需要扩容,长度扩大成原来的1.5倍。add(E e) 在
size赋值添加数据add(int index, E element) 将数组从
index往后移动一位,新数据添加到index上。获取数据
get(int index)利用数组的特定,根据下标获取数据。remove(int index)将index之后的数据全部往前移动一位,size - 1赋为null。
版权声明: 本文为 InfoQ 作者【Jeremy Lai】的原创文章。
原文链接:【http://xie.infoq.cn/article/01e2f6071e2095f29a9a5de7e】。文章转载请联系作者。









评论