一、初始化
我们有三种初始化办法:无参数直接初始化、指定大小初始化、指定初始数据初始化。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//无参数直接初始化,数组大小为空public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}//指定初始数据初始化public ArrayList(Collection<? extends E> c) {//elementData 是保存数组的容器,默认为 nullelementData = c.toArray();//如果给定的集合(c)数据有值if ((size = elementData.length) != 0) {// c.toArray might (incorrectly) not return Object[] (see 6260652)//如果集合元素类型不是 Object 类型,我们会转成 Objectif (elementData.getClass() != Object[].class) {elementData = Arrays.copyOf(elementData, size, Object[].class);}} else {// 给定集合(c)无值,则默认空数组this.elementData = EMPTY_ELEMENTDATA;}}
注意:ArrayList无参构造器初始化时,默认大小是空数组,并不是大家常说的10,10是在第一次add的时候扩容的数组值
二、新增和扩容实现
新增就是往数组中添加元素,主要分成两步:
1、判断是否要扩容,如果需要执行扩容操作
2、直接赋值
public boolean add(E e) {//确保数组大小是否足够,不够执行扩容,size 为当前数组的大小ensureCapacityInternal(size + 1); // Increments modCount!!//直接赋值,线程不安全的elementData[size++] = e;return true;}private void ensureCapacityInternal(int minCapacity) {//如果初始化数组大小时,有给定初始值,以给定的大小为准,不走 if 逻辑if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);}//确保容积足够ensureExplicitCapacity(minCapacity);}private void ensureExplicitCapacity(int minCapacity) {//记录数组被修改modCount++;// 如果我们期望的最小容量大于目前数组的长度,那么就扩容if (minCapacity - elementData.length > 0)grow(minCapacity);}//扩容,并把现有数据拷贝到新的数组里面去private void grow(int minCapacity) {int oldCapacity = elementData.length;// oldCapacity >> 1 是把 oldCapacity 除以 2 的意思int newCapacity = oldCapacity + (oldCapacity >> 1);// 如果扩容后的值 < 我们的期望值,扩容后的值就等于我们的期望值if (newCapacity - minCapacity < 0)newCapacity = minCapacity;// 如果扩容后的值 > jvm 所能分配的数组的最大值,那么就用 Integer 的最大值if (newCapacity - MAX_ARRAY_SIZE > 0)elementData = Arrays.copyOf(elementData, newCapacity);}
注意:
1、扩容的规则并不是翻倍,是原来容量大小+容量大小的一半,直白来说,就是扩容的大小是原来容量的1.5倍
2、ArrayList中的数组的最大值是Integer.MAX_VALUE,超过个值,JVM就不会给数组分配内存空间了
3、新增时,并没有对值进行严格的校验,所以ArrayList是允许null值的
