JDK1.8 源码分析(四)--ArrayList

323 阅读11分钟

1. 类的定义

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

从定义中可以看出

  • ArrayList是一个泛型类
  • ArrayList继承了AbstractList抽象类
  • ArrayList实现了List接口
  • ArrayList实现了RandomAccess接口,表示ArrayList支持随机访问,实质就是ArrayList是一个Object类型的数组,无法创建泛型数组
  • ArrayList实现了Cloneable接口,表示ArrayList支持克隆
  • ArrayList实现了java.io.Serializable接口,表示ArrayList支持序列化

ArrayList继承类图

2.字段属性

	//序列化版本号
    private static final long serialVersionUID = 8683452581122892189L;
	//默认容量为10
    private static final int DEFAULT_CAPACITY = 10;
	//容量为0的时候的默认空数组
    private static final Object[] EMPTY_ELEMENTDATA = {};
	//初始化时默认空数组,因为有可能不存放元素
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
	//真正存储数据的地方, 当第一次添加数据的时候容量会扩容到DEFAULT_CAPACITY(10)
	//transient修饰表示序列化会被忽略
    transient Object[] elementData; // non-private to simplify nested class access
	//有效数据的长度,不一定等于elementData的长度
    private int size;
	//最大容量
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
	//修改次数,从父类继承来的
    protected transient int modCount = 0;

3.构造函数

 	//指定容量的构造函数
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            //如果指定容量大于0,则创建指定容量大小的数组
            //注意数组类型不是泛型,而是Object,无法创建泛型数组
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            //如果指定容量为0,则使用默认的EMPTY_ELEMENTDATA
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            //容量小于0抛出异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

    //不带参数的构造函数,默认使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA初始化
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

	//传入一个集合作为参数的构造函数
    public ArrayList(Collection<? extends E> c) {
        //把集合内容转换为数组赋值给elementData
        elementData = c.toArray();
        //给size赋值
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            //如果传入的集合不是Object类型需要强转后再拷贝得到新的数组再赋值给elementData
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            //如果长度为0则把EMPTY_ELEMENTDATA赋值给elementData
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

从上面可以看出

  • 可以传入一个int类型的容量来初始化一个ArrayList
  • ArrayList有默认不带参数的构造函数
  • 可以传入一个Collection对象来初始化一个ArrayList
  • 不传入容量默认使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA作为elementData的值,容量为0使用EMPTY_ELEMENTDATA作为elementData的值

4.方法

size 方法

public int size() {
    	//直接返回size,说明size是可用元素的长度
        return size;
    }

isEmpty 方法

public boolean isEmpty() {
    	//如果size等于0就表示ArrayList为空
        return size == 0;
    }

contains 方法

public boolean contains(Object o) {
    	//直接调用indexOf方法,大于等于0就表示存在
        return indexOf(o) >= 0;
    }

indexOf 方法

 public int indexOf(Object o) {
        if (o == null) {
            //如果为空使用==来判断是否相等
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            //如果不为空使用equals来判断是否相等
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }
  • lastIndexOf方法和indexOf方法原理相同,不同在于for循环一个递增,一个递减

clone 方法

public Object clone() {
        try {
            //调用父类的克隆方法,此处可以看出ArrayList的克隆为浅拷贝,如果是引用类型只拷贝了引用
            ArrayList<?> v = (ArrayList<?>) super.clone();
            //赋值elementData的值
            v.elementData = Arrays.copyOf(elementData, size);
            //将修改统计数量置为0
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
    }

toArray 方法

 public Object[] toArray() {
     	//调用Array的copyOf方法,复制一个新的数组
        return Arrays.copyOf(elementData, size);
    }
 //传入一个目标数组
 public <T> T[] toArray(T[] a) {
        if (a.length < size)
            //如果目标数组的长度小于size创建一个长度为size的新数组
            //再把element的内容赋值到新数组中,返回新数组
            //Arrays.copyOf内部调用的也是System.arraycopy,相当于前面有一个扩容的功能
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
     	//如果目标数组的长度大于等于size,则直接赋值elementData的内容到目标数组中去
        System.arraycopy(elementData, 0, a, 0, size);
     	//如果目标数组的长度大于size,把size的值置为null
        if (a.length > size)
            a[size] = null;
        return a;
    }

get 方法

public E get(int index) {
    	//检查数组下标是否越界
        rangeCheck(index);
    	//返回目标位置的值
        return elementData(index);
    }
private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
E elementData(int index) {
        return (E) elementData[index];
    }

set 方法

public E set(int index, E element) {
    	//检查数组下标是否越界
        rangeCheck(index);
    	//获取旧值
        E oldValue = elementData(index);
    	//设置新值
        elementData[index] = element;
    	//返回旧值
        return oldValue;
    }

add 方法

public boolean add(E e) {
        //检查容量,如果容量不够则需要扩容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
    	//赋值并且将可用元素统计加1
        elementData[size++] = e;
        return true;
    }

public void add(int index, E element) {
    	//检查下标的合法性
        rangeCheckForAdd(index);
        //检查容量,如果容量不够则需要扩容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
    	//使用System.arraycopy进行移动,把index位置的元素向后移动一个位置,把index的位置腾出来
    	//性能较低
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
    	//为index的位置赋值
        elementData[index] = element;
    	//可用元素统计加1
        size++;
    }
//检查容量,如果容量不够则需要扩容
private void ensureCapacityInternal(int minCapacity) {
    	//如果elementData是默认初始化容量,则在默认容量和传入的容量中取最大值进行是否扩容比较
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
    	//检查是否扩容
        ensureExplicitCapacity(minCapacity);
    }
//检查是否扩容
private void ensureExplicitCapacity(int minCapacity) {
    	//修改数量加1
        modCount++;
    	//如果需要的容量大于elementData的长度则需要扩容
        if (minCapacity - elementData.length > 0)
            //扩容
            grow(minCapacity);
    }
//扩容函数,这是重点
//默认扩容为原容量的1.5倍
private void grow(int minCapacity) {
        // 获取以前的容量
        int oldCapacity = elementData.length;
    	//新的容量长度为旧的容量的1.5倍
    	//oldCapacity >> 1 等同于 oldCapacity/2
        int newCapacity = oldCapacity + (oldCapacity >> 1);
    	//如果扩容后的容量还不够则将新容量大小替换为传入的容量大小
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
    	//如果新容量大于了最大可以设置的容量大小则进行最大容量检查
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // 最后使用Arrays.copyOf进行扩容
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
//最大容量检查
private static int hugeCapacity(int minCapacity) {
    	//如果容量超过Integer.MAX_VALUE,抛出异常
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
    	//大于默认的最大容量返回Integer.MAX_VALUE,其他则返回最大默认容量MAX_ARRAY_SIZE
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
//下标合法性检查
private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

remove 方法

public E remove(int index) {
    	//下标检查
        rangeCheck(index);
    	//修改统计加1
        modCount++;
    	//获取旧值
        E oldValue = elementData(index);
    	//计算移动的个数,删除元素相当于把删除位置后面的元素向前移动一个位置,最后把末尾的值置为null
        int numMoved = size - index - 1;
    	//如果移动数大于0,等于0表示删除最后一个元素,不存在小于0的情况
        if (numMoved > 0)
            //index+1位置和后面所有的元素向前移动一位
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
    	//把末尾的值置为0,并将可用元素个数减1
        elementData[--size] = null; // clear to let GC do its work
    	//返回旧值
        return oldValue;
    }

public boolean remove(Object o) {
        if (o == null) {
            //元素为空使用==比较,遍历元素进行比较
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    //找到则移除
                    fastRemove(index);
                    return true;
                }
        } else {
            //元素不为空使用equals比较,遍历元素进行比较
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                     //找到则移除
                    fastRemove(index);
                    return true;
                }
        }
    	//存在返回true,不存在返回false
        return false;
    }

private void fastRemove(int index) {
    	//修改统计加1
        modCount++;
    	//计算移动的个数,删除元素相当于把删除位置后面的元素向前移动一个位置,最后把末尾的值置为null
        int numMoved = size - index - 1;
    	//如果移动数大于0,等于0表示删除最后一个元素,不存在小于0的情况
        if (numMoved > 0)
            //index+1位置和后面所有的元素向前移动一位
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
    	//把末尾的值置为0,并将可用元素个数减1
        elementData[--size] = null; // clear to let GC do its work
    }
  • 注意:remove(Object 0)方法只移除一个元素

clear 方法

public void clear() {
    	//修改统计加1
        modCount++;
        //遍历,将所有元素置为null
        for (int i = 0; i < size; i++)
            elementData[i] = null;
    	//把可用元素置为0
        size = 0;
    }

addAll 方法

public boolean addAll(Collection<? extends E> c) {
    	//将传入的Collection转换为数组
        Object[] a = c.toArray();
    	//获取转换后的长度
        int numNew = a.length;
    	//检查容量并扩容
        ensureCapacityInternal(size + numNew);  // Increments modCount
    	//使用System.arraycopy转换后的数组内容追加到elementData后面
        System.arraycopy(a, 0, elementData, size, numNew);
    	//重新计算可用元素大小
        size += numNew;
    	//如果转换后的长度不等于0返回ture反之返回false
        return numNew != 0;
    }

public boolean addAll(int index, Collection<? extends E> c) {
    	//检查下标合法性
        rangeCheckForAdd(index);
		//将传入的Collection转换为数组
        Object[] a = c.toArray();
    	//获取转换后的长度
        int numNew = a.length;
    	//检查容量并扩容
        ensureCapacityInternal(size + numNew);  // Increments modCount
		//计算移动数量
        int numMoved = size - index;
        if (numMoved > 0)
            //使用System.arraycopy将index位置和后面素有的元素向后移动numNew位
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);
		//将a的内容拷贝到elementData中去,拷贝目标位置从index处开始
        System.arraycopy(a, 0, elementData, index, numNew);
    	//重新计算可用元素大小
        size += numNew;
    	//如果转换后的长度不等于0返回ture反之返回false
        return numNew != 0;
    }

removeAll 方法

public boolean removeAll (Collection<?> c) {
    	//参数检查,如果参数为空,抛出异常
        Objects.requireNonNull(c);
    	//批量移除
        return batchRemove(c, false);
    }

private boolean batchRemove(Collection<?> c, boolean complement) {
    	//拷贝elementData
        final Object[] elementData = this.elementData;
    	//r表示遍历的值,w表示符合条件的数量
        int r = 0, w = 0;
    	//是否被修改
        boolean modified = false;
        try {
            //遍历elementData
            for (; r < size; r++)
                //complement为false表示c中不包含该元素则把该元素加入到elementData
                if (c.contains(elementData[r]) == complement)
                    //如果符合条件加入到elementData开始位置,并加w加1
                    elementData[w++] = elementData[r];
        } finally {
            //r不等于size表示在r的位置抛出了异常
            //抛出异常后默认后面的都符合(c.contains(elementData[r]) == complement)条件
            if (r != size) {
                //把r后面的值拷贝到w后面去
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                //把r到size的部分加到w上
                w += size - r;
            }
            //如果w不等于size表示有一部分符合条件
            //把w后面的部分置为null
            if (w != size) {
                // clear to let GC do its work
                //把w后面的部分置为null
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                //重新计算修改统计值
                modCount += size - w;
                //重新计算当前可用元素的数量
                size = w;
                //设置为被修改
                modified = true;
            }
        }
        return modified;
    }

subList 方法

public List<E> subList(int fromIndex, int toIndex) {
    	//检查下标的合法性
        subListRangeCheck(fromIndex, toIndex, size);
    	//返回一个SubList,SubList是ArrayList的一个私有的内部类
        return new SubList(this, 0, fromIndex, toIndex);
    }

forEach 方法

 @Override
    public void forEach(Consumer<? super E> action) {
        //检查action是否为空,为空抛出异常
        Objects.requireNonNull(action);
        //拷贝一份modCount,用final修饰
        final int expectedModCount = modCount;
        @SuppressWarnings("unchecked")
        final E[] elementData = (E[]) this.elementData;
        final int size = this.size;
        //for循环调用action的accept
       	//通过modCount == expectedModCount保证for循环中ArrayList不被修改
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            action.accept(elementData[i]);
        }
        //如果forEach中ArrayList被修改了,抛出异常
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }

removeIf 方法

 @Override
    public boolean removeIf(Predicate<? super E> filter) {
        //检查filter是否为空
        Objects.requireNonNull(filter);
        //初始化移除的数量为0
        int removeCount = 0;
        //使用BitSet来保存要移除的小标
        final BitSet removeSet = new BitSet(size);
        //拷贝一份modCount并用final修饰,保证ArrayList不被外部修改
        final int expectedModCount = modCount;
        //拷贝一份size
        final int size = this.size;
        //for循环遍历
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            @SuppressWarnings("unchecked")
            //获取当前遍历位置的元素
            final E element = (E) elementData[i];
            //判断元素是否符合删除条件
            if (filter.test(element)) {
                //符合条件把下标记录到removeSet中
                removeSet.set(i);
                //删除数量加1
                removeCount++;
            }
        }
        //如果中途被修改抛出异常
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }

     	//判断是否有满足删除条件的元素
        final boolean anyToRemove = removeCount > 0;
        if (anyToRemove) {
            //计算新的可用元素数量
            final int newSize = size - removeCount;
            //BitSet的用法还不太清楚,在这猜想是保存下标
            //for循环中大概是把不删除的复制到最前面
            //最后再把newSize后面的都置为null
            for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
                i = removeSet.nextClearBit(i);
                elementData[j] = elementData[i];
            }
            //把尾部元素置为空,有效元素数量只有newSize
            for (int k=newSize; k < size; k++) {
                elementData[k] = null;  // Let gc do its work
            }
            //计算新的有效元素数量
            this.size = newSize;
            //如果中途被修改抛出异常
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }

        return anyToRemove;
    }

replaceAll 方法

@Override
    @SuppressWarnings("unchecked")
    public void replaceAll(UnaryOperator<E> operator) {
        //检查operator是否为空,为空抛出异常
        Objects.requireNonNull(operator);
        //拷贝一份modCount并用final修饰,保证ArrayList不被外部修改
        final int expectedModCount = modCount;
        //拷贝一份size
        final int size = this.size;
        //for循环遍历
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            //调用operator.apply操作每个元素
            elementData[i] = operator.apply((E) elementData[i]);
        }
        //如果被修改则抛出异常
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        //修改统计加1
        modCount++;
    }

sort 方法

@Override
    @SuppressWarnings("unchecked")
    public void sort(Comparator<? super E> c) {
        //拷贝一份modCount并用final修饰,保证ArrayList不被外部修改
        final int expectedModCount = modCount;
        //调用Arrays.sort进行排序
        Arrays.sort((E[]) elementData, 0, size, c);
        //如果被修改则抛出异常
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }

iterator 方法

public Iterator<E> iterator() {
        return new Itr();
    }
  • Itr是ArrayList的一个内部类
  • Itr的类定义
private class Itr implements Iterator<E>

listIterator 方法

public ListIterator<E> listIterator() {
        return new ListItr(0);
    }

 public ListIterator<E> listIterator(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("Index: "+index);
        return new ListItr(index);
    }
  • ListItr是ArrayList的一个内部类
  • ListItr的类定义
private class ListItr extends Itr implements ListIterator<E>