ArrayList1.8源码分析

    ArrayList底层的数据结构是数组,它是线程不安全的,ArrayList允许元素为null,实现RandomAccess接口,表明List提供了随机快速访问功能,可以以O(1)的时间复杂度根据下标访问元素,本文就以JDK1.8源码为例深入探讨ArrayList的结构实现和功能原理。

类结构图

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


image.png

类注释

(1) ArrayList是一个动态数组,容量可以动态的增加,允许存储null元素。
(2) size、isEmpty、get、set、iterator、listIterator操作以恒定的时间运行,add操作在恒定的平摊时间内运行[也就是说添加n个元素需要0(n)的时间]。
(3) 每个ArrayList都包含一个capacity。
(4) 在添加大量元素之前使用ensureCapacity操作,可以减少增量重新分配的数量。
(5) ArrayList它是线程不安全,通过Collections.synchronizedList实现线程安全。

类常量

//无参构造方法创建对象时,ArrayList的默认初始化长度
private static final int DEFAULT_CAPACITY = 10;
//空的对象数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//空的对象数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//保存ArrayList对象的数组缓冲区,真正存放元素的数组[ArrayList底层是数组的实现]
//transient修饰的属性不会被序列化
transient Object[] elementData;  // non-private to simplify nested class access
//当前集合中实际元素的数量,与[elementData.length]是有区别
private int size;

构造函数

//无参构造方法
public ArrayList() {
    //将空数组赋值给elementData
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

//带初始容量的构造方法
public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        //新建一个长度为initialCapacity的Object数组.
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        //直接将EMPTY_ELEMENTDATA赋值给elementData
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        //容量小于0抛出异常
        throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
    }
}

//利用Collection集合来构建构造函数
public ArrayList(Collection c) {
    //利用Collection.toArray()方法得到一个Object[]数组,赋值给elementData
    elementData = c.toArray();
    //原数组size不为0
    if ((size = elementData.length) != 0) {
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        //c.toArray可能出错,返回类型不是Object
        if (elementData.getClass() != Object[].class)
            //修改集合c中为Object类型
            //利用Arrays.copyOf()来复制集合c中的元素到elementData数组中
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        //直接将EMPTY_ELEMENTDATA赋值给elementData
        this.elementData = EMPTY_ELEMENTDATA;
    }
}
//通过Arrays.copyOf()方法返回Object[]数组
public Object[] toArray() {
    return Arrays.copyOf(elementData, size);
}

@SuppressWarnings("unchecked")
public  T[] toArray(T[] a) {
    //a.length小于size
    if (a.length < size)
        // Make a new array of a's runtime type, but my contents:
        //返回一个新的数组
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    //a.length等于size,返回a数组
    System.arraycopy(elementData, 0, a, 0, size);
    //a.length大于size
    if (a.length > size)
        //把a[size]清空
        a[size] = null;
    return a;
}

//copyOf()的重载函数
@SuppressWarnings("unchecked")
public static  T[] copyOf(T[] original, int newLength) {
    return (T[]) copyOf(original, newLength, original.getClass());
}

//copyOf()的重载函数
public static  T[] copyOf(U[] original, int newLength, Class newType) {
    @SuppressWarnings("unchecked")
    //根据class的类型来决定是new还是反射去构造一个数组
    T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    //利用native函数,复制[original]元素至新的[copy]数组中 [常用函数]
    System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));
    return copy;
}

//System类中的native方法 
//src 原数组  srcPos 原数组开始拷贝的位置 
//dest 目标数组 destPos 目标数组开始拷贝的位置
//length 拷贝原数组的长度[开始位置 = srcPos]
public static native void arraycopy(Object src,int  srcPos,Object dest,int destPos,int length);

常用函数 - add

public boolean add(E e) {
    //判断add之后是否需要扩容
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    //[赋值]在数组末尾追加一个元素并修改size
    //等同于elementData[size] = e; size = size + 1;
    elementData[size++] = e;
    return true;
}

//调用ensureCapacityInternal(int minCapacity)
private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

//size默认值0添加一个元素时minCapacity=1,返回最小容量为10
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    //判断数组是否等于默认空的构造函数
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        //返回max(Capacity)
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    //数组不为空直接返回
    return minCapacity;
}

//调用ensureExplicitCapacity(int minCapacity)
private void ensureExplicitCapacity(int minCapacity) {
    //如果确定要扩容,会修改modCount
    modCount++;

    // overflow-conscious code
    //判断是否需要扩容
    if (minCapacity - elementData.length > 0)
        //执行扩容
        grow(minCapacity);
}

//第一次扩容是0到10,扩容有可能超过0.5倍或达不到0.5倍。
private void grow(int minCapacity) {
    // overflow-conscious code
    //获取数组长度[原数组容量]
    int oldCapacity = elementData.length;
    //新的容量等于原有容量 + 0.5 * oldCapacity [右移一位等于除以2]
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    //如果新容量小于最小容量,按照最小容量进行扩容
    //如果传入参数 > 1.5倍原容量,新容量 = 传入参数
    if (newCapacity - minCapacity < 0)
          newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        //计算最大容量,进行扩容
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    //调用Arrays.copyOf()方法扩容[拷贝],构建一个新的数组[new 或 反射]
    elementData = Arrays.copyOf(elementData, newCapacity);
}

//add(int index, E element)
public void add(int index, E element) {
    //判断是否越界[(index > size || index < 0)]
    rangeCheckForAdd(index);
    //判断add之后是否需要扩容
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    // //将index开始的数据向后移动一位[调用System.arraycopy],比较耗费资源
    System.arraycopy(elementData, index, elementData, index + 1,size - index);
    //空出来的index位置插入element元素
    elementData[index] = element;
    //数组中的元素 + 1
    size++;
}

//判断是否出现下标是否越界
private void rangeCheckForAdd(int index) {
    //index大于集合的大小或小于0提示越界
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

//异常输出处理
private String outOfBoundsMsg(int index) {
    return "Index: "+index+", Size: "+size;
}

//添加Collection集合元素
 public boolean addAll(Collection c) {
    //利用Collection.toArray()方法得到一个Object[]数组
    Object[] a = c.toArray();
    //获取数组长度
    int numNew = a.length;
    //判断是否需要扩容
    ensureCapacityInternal(size + numNew);  // Increments modCount
    //复制数组
    System.arraycopy(a, 0, elementData, size, numNew);
    //数组中的元素 + numNew
    size += numNew;
    return numNew != 0;
}

public boolean addAll(int index, Collection c) {
    //判断数组是否越界
    rangeCheckForAdd(index);
    //利用Collection.toArray()方法得到一个Object[]数组
    Object[] a = c.toArray();
    //获取数组长度
    int numNew = a.length;
    //判断是否需要扩容
    ensureCapacityInternal(size + numNew);  // Increments modCount
    //移动(复制)数组
    int numMoved = size - index;
    if (numMoved > 0)
      System.arraycopy(elementData, index, elementData, index + numNew,
                           numMoved);
    //复制数组完成批量赋值
    System.arraycopy(a, 0, elementData, index, numNew);
    //数组中的元素 + numNew
    size += numNew;
    return numNew != 0;
}

常用函数 - remove

public E remove(int index) {
    //判断是否越界
    rangeCheck(index);
    //修改modeCount,因为结构改变了
    modCount++;
    //读出index位置的元素
    E oldValue = elementData(index);
    //计算移动元素的数量
    int numMoved = size - index - 1;
    if (numMoved > 0)
        //拷贝覆盖数组数据
        System.arraycopy(elementData, index+1, elementData, index,numMoved);
    //清空原尾部数据,不再强引用,方便GC回收[避免内存泄露]
    elementData[--size] = null; // clear to let GC do its work
    //返回待删除的元素
    return oldValue;
}

//判断是否越界
private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

//获取指定位置元素
E elementData(int index) {
    return (E) elementData[index];
}

//删除数组中第一次出现位置上的数据,删除成功返回true
public boolean remove(Object o) {
    //判断对象是否为空
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                //根据index删除指定元素
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                //根据index删除指定元素
                fastRemove(index);
                return true;
            }
    }
    return false;
}

private void fastRemove(int index) {
    //修改modCount
    modCount++;
    //计算移动元素的数量
    int numMoved = size - index - 1;
    if (numMoved > 0)
        //拷贝覆盖数组数据[index后面的元素向前移动一位]
        System.arraycopy(elementData, index+1, elementData, index,numMoved);
    //清空原尾部数据,不再强引用,方便GC回收
    elementData[--size] = null; // clear to let GC do its work
}

protected void removeRange(int fromIndex, int toIndex) {
    //修改modCount
    modCount++;
    //计算移动元素的数量
    int numMoved = size - toIndex;
    //把toIndex后面的元素拷贝到fromIndex后面
    System.arraycopy(elementData,toIndex,elementData,fromIndex,numMoved);
    // clear to let GC do its work
    //得到新的长度
    int newSize = size - (toIndex-fromIndex);
    //新长度后面的元素清空
    for (int i = newSize; i < size; i++) {
        elementData[i] = null;
    }
    //计算新的数组长度
    size = newSize;
}

//批量删除-底层调用batchRemove
public boolean removeAll(Collection c) {
    //判断集合是否为空,为空抛出NPE
    Objects.requireNonNull(c);
    //批量删除[complement = false]
    return batchRemove(c, false);
}

//取交集-底层调用batchRemove
public boolean retainAll(Collection c) {
    Objects.requireNonNull(c);
    //批量删除[complement = true]
    return batchRemove(c, true);
}

//批量删除 complement = [false | true] 
private boolean batchRemove(Collection c, boolean complement) {
    //初始化数组
    final Object[] elementData = this.elementData;
    //w是删除之后数组中剩余数量
    int r = 0, w = 0;
    boolean modified = false;
    try {
        for (; r < size; r++)//高效保存[删除和取交集通用方法]
            //如果c.contains(elementData[r]) == complement,保留elementData[r]元素
            if (c.contains(elementData[r]) == complement)
                //数据赋值并保留,[complement有可能是true|false]
                elementData[w++] = elementData[r];
    } finally {
        // Preserve behavioral compatibility with AbstractCollection,
        // even if c.contains() throws.
       //正常情况下r == size,出现ClassCastException[类转换异常]下r != size
       if (r != size) {
            //把r位置之后的元素拷贝到w位置之后
            System.arraycopy(elementData,r,elementData,w,size - r);
            //数组元素数量增加
            w += size - r;
        }
        if (w != size) {
            //删除w位置之后的元素
            // clear to let GC do its work
            for (int i = w; i < size; i++)
                //置空,方便GC回收
                elementData[i] = null;
            //删除size - w次
            modCount += size - w;
            //数组中剩余数量
            size = w;
            //删除成功返回true
            modified = true;
        }
    }
    return modified;
}

常用函数 - set

public E set(int index, E element) {  
    //检查是否越界
    rangeCheck(index);
    //获取元素
    E oldValue = elementData(index);
    //覆盖元素
    elementData[index] = element;
    //返回oldValue
    return oldValue;
}

常用函数 - get

public E get(int index) {
    //检查是否越界
    rangeCheck(index);
    //获取指定下标元素
    return elementData(index);
}

//获取指定下标元素
E elementData(int index) {
    //实际存储数据的数组elementData
    return (E) elementData[index];
}

常用函数 - clear

public void clear() {
    //修改modCount
    modCount++;
    // clear to let GC do its work
    //清空elementData数组,方便GC回收
    for (int i = 0; i < size; i++)
        elementData[i] = null;
    //修改size = 0
    size = 0;
}

常用函数 - size

public int size() {
    //返回当前集合中实际元素的数量
    return size;
}

//判断集合是否为空
public boolean isEmpty() {
    return size == 0;
}

常用函数 - contains

public boolean contains(Object o) {
    //判断集合中是否包含该元素
    return indexOf(o) >= 0;
}

//对象循环查找获取首次出现位置
public int indexOf(Object o) {
    if (o == null) {
        //对象为空,遍历集合
        for (int i = 0; i < size; i++)
            if (elementData[i]==null)
                //返回元素首次出现位置
                return i;
    } else {
        //对象不为空,遍历集合
        for (int i = 0; i < size; i++)
            if (o.equals(elementData[i]))
                //返回元素首次出现位置
                return i;
    }
    //对象不存在,返回 -1
    return -1;
}

//对象循环查找获取最后一次出现位置
public int lastIndexOf(Object o) {
    //对象为空,遍历集合,空用"=="判断
    if (o == null) {
        for (int i = size-1; i >= 0; i--)
            if (elementData[i]==null)
                //返回元素最后一次出现位置
                return i;
    } else {
        //对象不为空,遍历集合,用"equals()"判断
        for (int i = size-1; i >= 0; i--)
            if (o.equals(elementData[i]))
                //返回元素最后一次出现位置
                return i;
    }
    //对象不存在,返回 -1
    return -1;
}

常用函数 - trimToSize

//将底层数组的容量调整为当前实际元素的大小,解决空间
public void trimToSize() {
    modCount++;
    //实际元素的大小 小于 当前数组长度
    if (size < elementData.length) {
        //进行缩容
        elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size);
    }
}

常用函数 - clone

public Object clone() {
    try {
        //数组克隆
        ArrayList v = (ArrayList) super.clone();
        //拷贝并赋值给v
        v.elementData = Arrays.copyOf(elementData, size);
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

常用函数 - Iterator

public Iterator iterator() {
    return new Itr();
}

private class Itr implements Iterator {
    //默认是0
    int cursor;       // index of next element to return
    //上一次返回的元素位置
    int lastRet = -1; // index of last element returned; -1 if no such
    //用于判断集合是否修改过结构的标志
    int expectedModCount = modCount;
    //空的构造函数
    Itr() {}
    //游标是否移动至数组尾部
    public boolean hasNext() {
      return cursor != size;
    }

    @SuppressWarnings("unchecked")
    public E next() {
        //判断是否修改过
        checkForComodification();
        int i = cursor;
        //判断是否越界
        if (i >= size)
            throw new NoSuchElementException();
        //获取elementData元素
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        //游标 + 1
        cursor = i + 1;
        //返回元素 ,并设置上一次返回的元素的下标
        return (E) elementData[lastRet = i];
}

public void remove() {
    //是否执行或next()
    if (lastRet < 0)
        throw new IllegalStateException();
    //判断是否修改过
    checkForComodification();
    try {
        //删除元素remove方法内会修改modCount
        ArrayList.this.remove(lastRet);
        //要删除的游标
        cursor = lastRet; 
        //不能重复删除 所以修改删除的标志位
        lastRet = -1;
        //更新判断集合是否修改的标志
        expectedModCount = modCount;
    } catch (IndexOutOfBoundsException ex) {
        throw new ConcurrentModificationException();
    }
}

//判断是否修改过了List的结构,如果有修改,抛出异常[并发处理]
final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
    }
}

常用函数 - 序列化反序列化

//序列化
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{
    // Write out element count, and any hidden stuff
    //fail-fast机制,用于后续判断是否有并发处理
    int expectedModCount = modCount;
    //序列化没有标记为static、transient的字段
    s.defaultWriteObject();
    // Write out size as capacity for behavioural compatibility with clone()
    s.writeInt(size);
    // Write out all elements in the proper order.
    //按照size的大小进行序列化[没有直接序列化elementData数组]
    for (int i=0; i

扩展问题

ArrayList和LinkedList的区别

(1) ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
(2) 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
(3) 对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。

ArrayList和Vector的区别

(1) Vector和ArrayList几乎是完全相同的[底层都是数组],唯一的区别在于Vector是同步类(synchronized),因此开销就比ArrayList要大、访问要慢。
(2 ) Vector每次扩容是其大小的2倍空间,而ArrayList扩容是1.5倍。
(3) Vector还有一个子类Stack。

以上为个人对ArrayList1.8源码的总结。

你可能感兴趣的:(ArrayList1.8源码分析)