啥也不说了,直接撸源码:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

从上述代码中我们可以看出继承了AbstractListList接口,实现了RandomAccessCloneable两个接口,其中RandomAccess接口中没有任何方法,他只是一个标识,说明实现该接口的类是一个可以随机访问的类方便查询,Cloneable 是标记型的接口,它们内部都没有方法和属性,实现Cloneable来表示该对象能被克隆,能使用Object.clone()方法。如果没有实现 Cloneable的类对象调用clone()就会抛出CloneNotSupportedException


今天我们重点看的是ArrayList中的add方法:

1.先说几个关键的几个全局变量:

//用于定于初始的大小
 private static final int DEFAULT_CAPACITY = 10;
//默认初始容量。
 private static final Object[] EMPTY_ELEMENTDATA = {
   };
//用于空实例的共享空数组实例
 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
   };
//操作数组
transient Object[] elementData;
//ArrayList的大小(它包含的元素数)
private int size;

2.构造器

//给定初始大小
public ArrayList(int initialCapacity) {
   
  //判断initialCapacity是否大于0
        if (initialCapacity > 0) {
   
  //如果大于0,则将initialCapacity作为ArrayList的初始大小 
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
   
 //如果等于0则将赋值一个空数组作为ArrayList的初始容量 
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
   
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
//在使用无参构造时,默认给ArrayList初始容量为0
public ArrayList() {
   
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

从上面的两个构造器可以看出ArrayList底层实现是数组,并且在不给定初始大小时,默认大小为0。


3.添加方法add()

public boolean add(E e) {
   
   //size记录的是ArrayList的大小(它包含的元素数),并加让当前seiz+1
        ensureCapacityInternal(size + 1);  
        //对组大小进行判断或扩容完成后,将新的元素添加大最后一个位置
        elementData[size++] = e;
        //返回true,表示添加成功
        return true;
    }

ArrayList在调用add方法添加元素时,首先会调用ensureCapacityInternal(size + 1)方法,对数组大小进行判断及扩容如下分析:

//minCapacity为实际元素个+1的大小
 private void ensureCapacityInternal(int minCapacity) {
   
// elementData为容纳元素的数组
//minCapacity为实际元素个+1的大小
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

发现ensureCapacityInternal方法内部又调用了ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));方法,
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));中他先调用的是calculateCapacity(elementData, minCapacity)方法:

// elementData为容纳元素的数组
//minCapacity为实际元素个+1的大小
private static int calculateCapacity(Object[] elementData, int minCapacity) {
   
//判断当数组是否为空数组,如果 elementData为空说明刚初始化的新实例对象, 
//准备添加一个元素
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
   
//给初始化新实例分配容量:10 
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
//如果elementData不为空说明刚此实例对象不是新初始化的,已经有元素了
//返回数据的实际大小 
        return minCapacity;
    }
//通过之前的判断得到数据的大小minCapacity
private void ensureExplicitCapacity(int minCapacity) {
   
        modCount++;
        //用数组中实际元素个数-数组长度
        //如果结果>0,说明元素个数已经超过的数组的大小,不能继续添加元素,需要进行数组扩容
        //如果结果<0,说明元素个数还没有超过的数组的大小,还可以继续添加元素
        if (minCapacity - elementData.length > 0)
        //扩容:minCapacity为实际元素个数+1
            grow(minCapacity);
    }
 private void grow(int minCapacity) {
   
       //得到数组的大小
        int oldCapacity = elementData.length;
        //通过位运算得到新数组的大小:旧数组大小+旧数组的大小的一半
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //判断新数组大小是否大于当前数组元素个数+1的大小
        if (newCapacity - minCapacity < 0)
        //如果newCapacity - minCapacity < 0说明新长度不能满足
        //则将minCapacity当做新的数组长度
            newCapacity = minCapacity;  
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
       //对数组进行扩容将elementData大小扩容为新的长度,并将老数组中大元素移动到新的数组中
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

扩展:

Arrays的copyOf()方法传回的数组是新的数组对象,改变传回数组中的元素值,不会影响原来的数组。
copyOf()的第二个自变量指定要建立的新数组长度,如果新数组的长度超过原数组的长度,则保留数组默认值,例如:

import java.util.Arrays;

public class ArrayDemo {
   
public static void main(String[] args) {
   
    int[] arr1 = {
   1, 2, 3, 4, 5}; 
    int[] arr2 = Arrays.copyOf(arr1, 5);
    int[] arr3 = Arrays.copyOf(arr1, 10);
    for(int i = 0; i < arr2.length; i++) 
        System.out.print(arr2[i] + " "); 
    System.out.println();
    for(int i = 0; i < arr3.length; i++) 
        System.out.print(arr3[i] + " ");
}
} 

结果:

1 2 3 4 5 
1 2 3 4 5 0 0 0 0 0