(第一次写博客,写得不好的地方请多多包涵 本人大二,有志同道合的朋友可以一起学习)
1、继承关系
ArrayList是基于动态数组实现,数组是根据索引来查找,所以查询较快,与数组相比,它的容量能动态的增长
由上图可知它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口,所以它也具有随机访问、克隆、可序列化等一些列功能。
2、相关成员变量
defalut_capacity:默认初始容量。
empty_elementdata:空数组,调用无参构造时默认给个空数组
default tacpacity_empty_elementdata:也是一个空数组。将它与empty_elementdata分开,以便确定当添加了第一个成员之后扩充多大
elementData:动态数组,
size:动态数组的实际大小
3、构造函数
指定初始容量的构造函数
指定collection构造的构造函数
4、添加数据
①
②
首先会进入到一个valueOf方法,因为我定义的是一个Integer的list所以当我存入一个int值的时候,会调用Integer类的静态方法valueOf(如果整型字面量的值在-128到127之间,那么不会new新的Integer对象,而是直接引用常量池中的Integer对象)这个简单了解即可
③
进入到add方法,这时size为0并且elementData也为一个空数组(图①用的无参构造,默认容量为10,并赋一个空的object数组给elementData)并至少容纳minCapacity个成员数量
④
进入到ensureCapacityInternal方法中,调用ensureExplicitCapacity,在此之前会先调用calculateCapacity方法
⑤
判断elementData是否为空,是就返回默认容量和minCapacity中的最大的哪一个 否则直接返回minCapacity
⑥
由图④可知此时进入ensureExplicitCapacity方法 (modCount用来记录修改次数,主要用于多线程环境下) 判断是否需要进行扩容
⑦
oldCapacity存储旧容量,newCapacity存储新容量,也就是扩容之后的
newCapacity等于oldCapacity加上oldCapacity左移一位(右移一位就是除以2的1次方,位运算要快于整除) 从这里也就可以看出Arraylist是以1.5倍来扩容的
如果扩容之后的newCapacity < oldCapacity 那么还是以原来的
如果扩容之后的newCapacity> max_array_size(2147483639) 那么就得调用hugeCapacity方法(但这个hugeCapacity估计也不会用到)
这里max_array_size=Integer.max_value-8
注意subList方法
我们经常会想只操作特定范围内的数据 那么就会用到subList 但这里直接调用subList方法的时候需要注意会改变原list 我们先跟进去看看
subListRangeCheck方法会先检测下你指定范围是否合法
然后再new一个新集合 但从上图可以看到 这里传了this 也就是说传入原list进去(这里subList是个内部类)
进入SubList的构造后 我们发现它的size是为我指定范围的长度 offset是指当前subList在原list中的起始位置
所以此时的add操作 会对原list进行操作