ArrayList源码阅读

ArrayList源码阅读

属性字段

private static final long serialVersionUID = 8683452581122892189L;
    //默认大小
    private static final int DEFAULT_CAPACITY = 10;
    //空数组
    private static final Object[] EMPTY_ELEMENTDATA = {};
    //从EMPTY_ELEMENTDATA独立出来,专门用于无参构造函数时的指向,起标识作用
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    //默认数组
    transient Object[] elementData; // non-private to simplify nested class access

    private int size;

构造方法

1)无参构造函数

public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

2) 参数为容器大小的构造函数

public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            //创建数组
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            //指向空数组
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

3)参数为其他list的构造函数

public ArrayList(Collection c) {
        //指向新数组
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
             // c.toArray 可能返回的不是Object类型的数组所以加上下面的语句用于判断,
            //这里用到了反射里面的getClass()方法
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

add添加

直接再末位添加元素

public boolean add(E e) {
    //判断是否要扩容,并自增modCount
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    //添加元素
    elementData[size++] = e;
    return true;
}

指定位置添加元素

public void add(int index, E element) {
        //验证下标是否在指定范围
        rangeCheckForAdd(index);
        //判断是否要扩容,并自增modCount
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //复制数组,腾出空位
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        //添加元素
        elementData[index] = element;
        //大小加1
        size++;
    }

添加一个集合

public boolean addAll(Collection c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        //判断是否要扩容,并自增modCount
        ensureCapacityInternal(size + numNew);  // Increments modCount
        //复制
        System.arraycopy(a, 0, elementData, size, numNew);
        //大小改变
        size += numNew;
        return numNew != 0;
    }

扩容方法

ensureCapacityInternal()

实现对grow的封装

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

calculateCapacity()

第一次添加元素时,判断时扩容为默认大小,还是扩容为minCapacity.总感觉这是一个无用的方法

private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

ensureExplicitCapacity()

改变modCount,并判断是否需要扩容,

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

grow()

真正的扩容方法

private void grow(int minCapacity) {
    // overflow-conscious code
    //原来的大小
    int oldCapacity = elementData.length;
    //扩容为原来的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    //在扩容为原来的1.5倍还不满足条件的时候
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // 复制为一个新的数组
    elementData = Arrays.copyOf(elementData, newCapacity);
}

private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        //MAX_ARRAY_SIZE=8
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

remove删除

删除指定下标的元素

public E remove(int index) {
    //判断范围
    rangeCheck(index);
    //自增modCount
    modCount++;
    //获得要删除的值
    E oldValue = elementData(index);
    
    int numMoved = size - index - 1;
    if (numMoved > 0)
        //把后面的值全部向前挪一位
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    //最后以为置空,并减小数组大小size,    置空有利于GC回收
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}

删除指定元素

public boolean remove(Object o) {
    //如果要删除的元素是null,
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {//删除正常的值
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}
//和删除指定下标元素的方法一样。
private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

get方法

很简单的逻辑

public E get(int index) {
    //判断范围
    rangeCheck(index);
    //返回对应值
    return elementData(index);
}

set方法

public E set(int index, E element) {
    //判断范围
    rangeCheck(index);
    //获得旧元素
    E oldValue = elementData(index);
    //更新
    elementData[index] = element;
    //返回
    return oldValue;
}

你可能感兴趣的:(ArrayList源码阅读)