目录
因为 ArrayList 是 List 接口和 Collection 接口的实现类,所以它们的方法 ArrayList 也可以用。
1.首先找到 ArrayList-->Alt+7 看大纲 --> 找到空参构造
2.看到一个叫 "默认长度 _ 空 _元素数据" 赋值给了 “元素数据”
3.发现了 这个 "默认长度 _ 空 _元素数据" 的东西 其实是一个长度为 0 的数组
4.所以当空参创建集合对象时,此时集合元素的数量是 0
假设我们使用空参创建了一个集合,
并要添加一个元素“aaa”
1. 首先 add 方法接收参数,
并且 modCount++,表示集合操作次数加 1,
接着调用另一个 add 方法:
2.add 中的 add 方法:
因为 size 此时为 0,数组长度也为 0 所以进入 if 语句调用 grow()方法进行扩容
3.接着来看 grow 源码:
在 grow 内也调用了一个 grow 方法,并传入参数 1,
表示添加完当前元素之后的最小容量
4.grow 中的 grow 源码:
1 赋值给了 minCapacity
数组的长度到目前为止,没发生过变化,为 0
不满足 if 条件直接跳过,第一次添加数据的时候,会执行到else这里,
若在以后继续添加元素,就会执行 if 里面的代码
else 内将minCapacity 和DEFAULT_CAPACITY 进行了比较,看看DEFAULT_CAPACITY 内是什么
最后第二个 grow 方法原路返回一个长度为10的新数组,
5. 最后:
元素"aaa"放入底层新数组的 0 索引处,集合长度 size 变为 0+1=1。
现在假设之前底层创建的默认长度为 10 的数组已被存满了,
这时再存一个元素"aaa",看看底层逻辑是怎样的:
第一步还是看 add 方法:
首先 add 方法接收参数"aaa",
并且 modCount++,集合操作次数加 1,
接着调用另一个 add 方法:
2.add 中的 add 方法:
因为 size 此时为 10,数组长度也为 10, 所以进入 if 语句调用
grow()方法进行扩容:
3.现在看 grow 方法:
发现在 grow 内也调用了一个 grow 方法,并传入参数 11,
表示添加完当前元素之后的最小容量
4.grow 中的 grow 源码:
11 赋值给了 minCapacity
数组的长度到目前为止,没发生过变化,为 10,赋值给了old capacity 记录为老容量。
此时满足 if 条件(若是第一次存元素不会走 if),
在 if 内调用了一个Arrays Support 的 new Length 方法,并且传递了三个参数:
1.老容量
2. 理论增长容量 1,
3. 默认实际增长量是oldcapacity 进行右位移 1 的结果(10/21=5)。
我们来看看 newLength 方法:
(有个细节:这里为什么要将 minGrowth 和 preGrowth 进行比较
因为考虑到了一次添加多个元素的情况,如添加了一个长度为 100 的集合,这里的 minGrowth 就会是 100,经过比较最后取得增长量才会是 100,也就是说当添加元素个数超过了原来长度的一半时,就会以实际添加量为准进行扩容)
扩容后的长度用 preLength 接收,后面的 if 先不用看。
然后将扩容后的长度preLength =15 返回第二个 grow 方法的newCapacity 变量
然后调用了 Arrays 的 copyOf 方法:
根据长度 newCapacity :15创建新的数组
并把老数组中的所有数据全部拷贝到这个长度为 15 的新数组当中
最后将该数组原路返回
5.最后:
元素"aaa"放入底层新数组的 10 索引处,size 变为 10+1=11。