ArrayList原理
add方法
ArrayList对于无参的构造函数的默认容量是0【this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA】
如果给的是一个整数作为构造方法的参数,那就会调用一个传入的数目的数组
如果给的是一个集合作为构造方法的参数,那么会根据集合的大小创建elementData数组的初始容量。
当我们往数组里添加第一个数字的时候就会触发第一次扩容。第一次扩容就会创建一个长度为10的新的数组,然后把元素添加到新数组的索引0的位置,最后把新的数组替换掉新的数组,长度为0的数组就不再用了。
第一次扩容是10,第二次扩容是上一次容量的1.5倍
旧数组容量是10,存不下了就创建一个长度为15的新数组,然后把旧数组的元素拷贝到新数组中,再把新的元素追加到新数组的最后一个位置,最后把新的数组替换掉新的数组。旧数组没有引用指向它,就会当成垃圾回收掉。
说是1.5倍,但实际上是用二进制除法,新容量=右移一位+原来数组的长度。
前二十次扩容长度
0 10 15 22 33 49 73 109 163 244 366
549 823 1234 1851 2776 4146 6246 9369 14053 21079
addAll方法
两种情况:
① arrayList中有元素,使用addAll添加元素。
② arrayList中没有元素,使用addAll添加元素。
,第二种情况:
ArrayList<Integer> list = new ArrayList<>();
list.addAll( List.of(1, 2, 3)); //第一次扩容会扩容成10
ArrayList<Integer> list = new ArrayList<>();
list.addAll( List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
//扩容机制:max(List.of中的元素个数,list下一次扩容长度),如本次为max(11,0)
第二种情况(List中元素本来就有元素)
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(i);
}
list.addAll(List.of(1,2,3)); //15
list.addAll(List.of(1,2,3,4,5,6)); //16
System.out.println(list.size());
总结
扩容规则
- ArrayList() 会使用长度为零的数组
- ArrayList(int initialCapacity) 会使用指定容量的数组
- public ArrayList(Collection<? extends E> c) 会使用 c 的大小作为数组容量
- add(Object o) 首次扩容为 10,再次扩容为上次容量的 1.5 倍
- addAll(Collection c) 没有元素时,扩容为 Math.max(10, 实际元素个数),有元素时为 Math.max(原容量 1.5 倍, 实际元素个数)