成员变量
学习源码前,我们还是先看一下ArrayList中成员变量有哪些
构造函数
ArrayList一共有三个构造函数。
第一个:带有指定初始容量的构造函数
第二个:空参构造
第三个:包含指定集合的构造函数
OK,看完构造函数,我们接下来看ArrayList的添加和扩容操作
添加和扩容
第 1 次添加数据
首先看下面构造函数:
调用空参构造,成员变量 size 此时为 0,一切都是默认。第一次添加元素,调用 add 方法,add 方法如下:
追踪 ensureCapacityInternal 方法,方法如下:
通过这里,可以得到 calculateCapacity 方法计算结果为 10,此时 10 会作为参数传给 ensureExplicitCapacity 方法,ensureExplicitCapacity 方法如下:
条件满足,调用 grow 扩容方法,方法实现如下:
int newCapacity = oldCapacity + (oldCapacity >> 1)
这行代码说明了 Arraylist 底层扩容是以 1.5
倍扩容。然后扩容完毕之后,继续执行 add 方法中的elementData[size++] = e
语句,即往数组大小为10的数组中,索引为 0 的下标下添加元素。size大小在计算完成后会自增。大佬这里可以帮我解释一下,这里不太懂。
第 2 到第 10 次添加数据
假如这是我们第 10 次添加数据,那么此时 add 方法中 size 肯定是为 9 的,对吧?第 10 次,那么前面是有 9 个数据了,所以 size 为 9。那么传递到 ensureCapacityInternal 方法中的参数就为 10
然后 minCapacity 就是 10,传递到 calculateCapacity 方法,得到结果还是为 10。具体可以参考上述(第一次添加元素的源码)源码比对分析一下。
接下来就是重点,ensureExplicitCapacity 这个方法此时 minCapacity=10,elementData.length=10(第一次添加元素的时候,就直接把 10 给了elementData.length),如下图所示:
所以 minCapacity - elementData.length 结果为 0,并没有大于 0,条件不成立,是不会进行扩容的。那么我们可以得出,在第 2 次到第 10 次的时候,都是不会进行扩容的。
第 11 次添加元素
第 11 次添加元素,说明之前已经存在了 10 个元素,那么就会进行扩容逻辑,以 1.5 倍进行扩容。
ArrayList 底层实现原理
ArrayList底层是用动态数组实现的,初始容量为 0,第一次扩容会初始化容量为 10,会以 1.5 倍进行扩容,每次扩容需要数组拷贝
ArrayList 和 LinkedList 区别是什么?
ArrayList 底层是动态数组
,LinkedList 底层是双向链表
ArrayList 按照索引查询,LinkedList 不支持下标查询
ArrayList 节省内存,LinkedList占用空间
两者都不线程安全