ArrayList源码解析(JDK1.8)

(第一次写博客,写得不好的地方请多多包涵 本人大二,有志同道合的朋友可以一起学习)

1、继承关系

ArrayList源码解析(JDK1.8)_第1张图片

ArrayList是基于动态数组实现,数组是根据索引来查找,所以查询较快,与数组相比,它的容量能动态的增长

由上图可知它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口,所以它也具有随机访问、克隆、可序列化等一些列功能。

2、相关成员变量

ArrayList源码解析(JDK1.8)_第2张图片

defalut_capacity:默认初始容量。

empty_elementdata:空数组,调用无参构造时默认给个空数组

default tacpacity_empty_elementdata:也是一个空数组。将它与empty_elementdata分开,以便确定当添加了第一个成员之后扩充多大

elementData:动态数组,

size:动态数组的实际大小

3、构造函数

指定初始容量的构造函数

ArrayList源码解析(JDK1.8)_第3张图片

 

指定collection构造的构造函数

ArrayList源码解析(JDK1.8)_第4张图片

4、添加数据

ArrayList源码解析(JDK1.8)_第5张图片

首先会进入到一个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

ArrayList源码解析(JDK1.8)_第6张图片

由图④可知此时进入ensureExplicitCapacity方法 (modCount用来记录修改次数,主要用于多线程环境下) 判断是否需要进行扩容 

ArrayList源码解析(JDK1.8)_第7张图片

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方法

ArrayList源码解析(JDK1.8)_第8张图片

我们经常会想只操作特定范围内的数据 那么就会用到subList 但这里直接调用subList方法的时候需要注意会改变原list 我们先跟进去看看

ArrayList源码解析(JDK1.8)_第9张图片

subListRangeCheck方法会先检测下你指定范围是否合法

然后再new一个新集合 但从上图可以看到 这里传了this 也就是说传入原list进去(这里subList是个内部类)

ArrayList源码解析(JDK1.8)_第10张图片

进入SubList的构造后 我们发现它的size是为我指定范围的长度 offset是指当前subList在原list中的起始位置 

所以此时的add操作 会对原list进行操作 

你可能感兴趣的:(ArrayList源码解析(JDK1.8))