ArrayList底层源码分析
ArrayList注意事项
- permits all elements, including null ,ArrayList可以加入null,并且多个
- ArrayList是由数组来实现数据存储的
- ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高)在多线程情况下,不建议使用ArrayList
ArrayList底层结构和源码分析
- ArrayList中维护了一个Object类型的数组elementData
- transient Object[] elementData;//该属性不会被序列化
- 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
0->10->15->22->33
- 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。
8->12->18->27
public static void main(String[] args) {
List<Integer> objects = new ArrayList<>();
for (int i = 0; i < 10; i++) {
objects.add(1);
}
for (int i = 0; i < 15; i++) {
objects.add(2);
}
objects.add(100);
objects.add(200);
}
无参构造器
new 无参构造器,创建了一个空的elementData数组
DEFAULTCAPACITY_EMPTY_ELEMENTDATA在后面calculateCapacity方法中==比较的就是这个,也就是说,如果你的elementData数组正好是DEFAULTCAPACITY_EMPTY_ELEMENTDATA代表你就是无参构造器创建的集合需要赋默认10 的容量
执行add方法
第一步ensureCapacityInternal(size + 1)。size没赋初值,默认为0。
先确定容量够吗,然后才执行elementData[size++] = e;把值放进数组里。
ensureCapacityInternal方法
elementData,前面的transient代表该属性不会被序列化
calculateCapacity方法
DEFAULTCAPACITY_EMPTY_ELEMENTDATA是一个空数组,在calculateCapacity方法中,如果传进来的恰好就是默认的空数组,那么会从默认容量和传进来的minCapacity容量,现在是1(size+1)挑一个最大的返回
所以返回10,也就是ensureCapacityInternal(10)
modCount++;是记录集合被修改的次数,防止多个线程同时修改。
如果当前的minCapacity(10)-elementData的长度>0就是说不够,就要扩容,grow(10)
旧的容量是数组的当前容量,新的=旧的+半个旧的,即扩容1.5倍,但一开始如果空参构造器旧的是0
0+0/2还是0,就不会扩容,进去第一个if,0-10<0成立把minCapacity(10)赋给newCapacity了。
如果你的新的容量比MAX_ARRAY_SIZE还大就使用hugeCapacity
然后用copyOf扩容,把elementData容量扩容成10 ,但还是为空(copyOf会保留之前的数组+上新的空间)
然后一层层返回到add方法,把数放到数组里
然后第二次add
上次elementData[size++]size赋值完加1了,所以现在的size是1即minCapacity是2
进去ensureCapacityInternal方法
现在的elementData已经有一个数了,追进去
地址不一样了,不满足条件,直接返回minCapacity,也就是2
然后modCount++;第二次修改
2-当前长度是10<0不满足,无需扩容,然后一层层返回到了add,把下一个数放进数组
到第11次,size是10,size+1=11
仍然返回minCapacity11
modCount是10,修改了10 次了,这次是第11次,满足if进入grow扩容方法
old是10,新的是10+5=15
走第一个if15-11>0不满足,第二个if也不满足,就直接把原数组的数据保留并且扩容到15
然后一层一层返回到add,把新的数放到底层的数组里
指定容量构造器
add第9个的时候
返回minCapacity
9-8>0满足,开始扩容
old是8,new是12,然后12-8<0不满足,所以直接把原数组数据保留并且扩容到12
一层层返回到add并且把数放到底层的数组中
Q.E.D.