ArrayList源码分析

属性

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

private static final long serialVersionUID = 8683452581122892189L;

/**
 * 默认的容量,当使用无参构造函数时,添加第一个数据,会创建此大小数组
 */
private static final int DEFAULT_CAPACITY = 10;

//private static final Object[] EMPTY_ELEMENTDATA = {};
//private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//会根据地址区分构造方法的使用,在数组扩容时,有体现

/**
 * 当使用有参构造函数时,此数组会赋值给元素数组
 */
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;

/**
 * 数组最大大小
 */
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

构造方法

/**
 * 使用参数的构造方法,参数符合条件,则成功创建
 * Object[] EMPTY_ELEMENTDATA = {};
 */
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);
    }
}

/**
 * 无参构造,赋值
 * Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
 */
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

/**
 * 
 * 根据其他集合对象创建集合,如果为空,则用有参对应的空数组
 */
public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // defend against c.toArray (incorrectly) not returning Object[]
        // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

自动扩容

/**
 * 门面方法
 */
private Object[] grow(int minCapacity) {
    //传入当前元素数组,和新扩容后的空数组容量
    return elementData = Arrays.copyOf(elementData,
                                       newCapacity(minCapacity));
}

/**
* 门面方法,将传入当前数组元素个数,因为要扩容,所以加一是其所需最小容量
*/
private Object[] grow() {
    return grow(size + 1);
}

/**
 *
 * 返回至少等于给定最小容量的容量。如果足够,返回当前容量增加50%的结果。除非给定的最小容量大于	  
 * MAX_ARRAY_SIZE,否则不会返回大于MAX_ARRAY_SIZE的容量。
 *
 * 核心
 */
private int newCapacity(int minCapacity) {
    // overflow-conscious code
    // 现元素数组长度
    int oldCapacity = elementData.length;
    // newCapacity = 1.5 * oldCapacity ------- 0 >> 1 = 0
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    //元素数组太小或太大所产生的错误  newCapacity <= minCapacity
    if (newCapacity - minCapacity <= 0) {
        //无参构造,第一次添加元素,地址比较  0-1 = -1
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        //数组已满,溢出int长度
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        //排除所有可能造成的问题,返回最小必须容量
        return minCapacity;
    }
    //newCapacity <= MAX_ARRAY_SIZE 新容量在范围中时,返回新容量,不然进行判断
    return (newCapacity - MAX_ARRAY_SIZE <= 0)
        ? newCapacity
        : hugeCapacity(minCapacity);
}

/**
* 一定保证能够存放数据
* minCapacity > MAX_ARRAY_SIZE时,返回int最大值,否则ArrayList容量最大值
*/
private static int hugeCapacity(int minCapacity) {
    //溢出
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE)
        ? Integer.MAX_VALUE
        : MAX_ARRAY_SIZE;
}

/**
 * 直接干扰数组容量
 */
public void ensureCapacity(int minCapacity) {
    if (minCapacity > elementData.length && 
        //无参创建初始且容量小于默认初次创建扩容量不允许干扰
        !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA && minCapacity <= 						DEFAULT_CAPACITY)) {
        modCount++;
        grow(minCapacity);
    }
}

增删改查

/**
 *
 * 先判断扩容,后增长,核心方法
 */
private void add(E e, Object[] elementData, int s) {
    if (s == elementData.length)
        elementData = grow();
    elementData[s] = e;
    size = s + 1;
}

/**
 * 门面方法,放入最后一个
 */
public boolean add(E e) {
    modCount++;
    add(e, elementData, size);
    return true;
}

/**
 * 核心
 */
public void add(int index, E element) {
    //检查下标是否合法
    rangeCheckForAdd(index);
    modCount++;
    final int s;
    Object[] elementData;
    //扩容
    if ((s = size) == (elementData = this.elementData).length)
        elementData = grow();
    System.arraycopy(elementData, index,
                     elementData, index + 1,
                     s - index);
    elementData[index] = element;
    size = s + 1;
}

/**
 *
 * 移除对应下标元素并返回
 */
public E remove(int index) {
    Objects.checkIndex(index, size);
    final Object[] es = elementData;

    @SuppressWarnings("unchecked") E oldValue = (E) es[index];
    fastRemove(es, index);

    return oldValue;
}

/**
 * 根据元素删除
 */
public boolean remove(Object o) {
    final Object[] es = elementData;
    final int size = this.size;
    int i = 0;
    found: {
        if (o == null) {
            for (; i < size; i++)
                if (es[i] == null)
                    break found;
        } else {
            for (; i < size; i++)
                if (o.equals(es[i]))
                    break found;
        }
        return false;
    }
    fastRemove(es, i);
    return true;
}

/**
 * 专用删除方法
 */
private void fastRemove(Object[] es, int i) {
    modCount++;
    final int newSize;
    //删除元素下标在范围内
    if ((newSize = size - 1) > i)
        //一种按要求复制方法
        //从原数组的下标i后的元素,复制到原数组,congi开始,复制 size - 1 - i 个
        System.arraycopy(es, i + 1, es, i, newSize - i);
    //最后一位元素因为不参与复制,所以设为null,垃圾回收
    es[size = newSize] = null;
}

扩充

/**
 * @param      src      the source array.
 * @param      srcPos   starting position in the source array.
 * @param      dest     the destination array.
 * @param      destPos  starting position in the destination data.
 * @param      length   the number of array elements to be copied.
 *
 * @param      src      源数组
 * @param      srcPos   起始位置
 * @param      dest     目标数组
 * @param      destPos  目标数据中的起始位置
 * @param      length   要复制的数组元素的数量

 */


public static native void arraycopy(Object src,  int  srcPos,
                                    Object dest, int destPos,
                                    int length);

/*
* 删除 3
* 结果 1 2 4 5 5
*/
public static void main(String[] args) {
    Integer[] ints = {1,2,3,4,5};
    System.arraycopy(ints,3,ints,2,2);
    for (int i = 0;i < ints.length;i++){
        System.out.println(ints[i]);
    }
}

/**
 * 更新下标元素
 */
public E set(int index, E element) {
    Objects.checkIndex(index, size);
    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}

/**
 *
 * 获取下标元素
 */
public E get(int index) {
    Objects.checkIndex(index, size);
    return elementData(index);
}

©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页