ArrayList源码分析

大纲

  • arrayList数据结构原理
  • arrayList源码分析

1. ArrayList数据结构原理

ArrayList的数据结构是使用了动态数组进行实现。通过判断数组中数据是否到达扩容值,当到达扩容值后,通过创建新的数组,复制老数组中的数据进入新的数组,从而实现动态扩容。

2. ArrayList源码分析

2.1 ArrayList的成员变量
    //数组的默认容量
    private static final int DEFAULT_CAPACITY = 10;
    //当ArrayList的构造方法中显示指出ArrayList的数组长度为0时,类内部将EMPTY_ELEMENTDATA 这个空对象数组赋给elemetData数组
    private static final Object[] EMPTY_ELEMENTDATA = {};
    //默认的空数组
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
  //定义的数组对象,作为存储数据的数组
    transient Object[] elementData; // non-private to simplify nested class access
  // 当前存储数据的长度
    private int size;
2.2 构造方法
//无参构造方法,默认给数组一个空对象
 public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
//定义初始容量的构造方法,大于0,通过当前容量创建数组,等于0给空对象,小于0报错。
    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);
        }
    }
  
    public ArrayList(Collection c) {
        //转换传入对象为Object[]数组
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
             //如果转换结果集不为Object[].class
            if (elementData.getClass() != Object[].class)
                //在进行一次转化
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            //如果为空,给个默认空数组
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }
2.3ArrayList的add()方法

add()主要做的事情确保数据正常插入到数组,插入数据如果超出当前数组长度,进行扩容。

    public boolean add(E e) {
        //确保当前容量增加1可以正常放入。
        ensureCapacityInternal(size + 1); 
        //添加参数,size长度增加1;
        elementData[size++] = e;
        return true;
    }
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    //计算容量 ,如果是调用的无参构造,默认为{},且第一次调用,
    获取size+1,与10的最大值返回。
 //如果不是给的默认值,说明有了容量,直接不用处理返回size+1的值。
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }
    private void ensureExplicitCapacity(int minCapacity) {
        //修改次数加一
        modCount++;

        // 判断size+1,是否大于数组的长度,如果大于,调用grow方法进行扩容。
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
  //扩容方法
    private void grow(int minCapacity) {
        // 获取老数组的长度
        int oldCapacity = elementData.length;
      //老数组的长度整体向左平移一位。变为以前的一半
      //所以新数组的容量为以前数组的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
     //如果扩容后的数组小于size+1的话。把size+1的长度给新数组。
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
          //如果新数组扩容或的容量大于数组的最大容量
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            //如果newcapacity大于最大容量,判断minCapacity是否大于最大容量,返回新容量
            newCapacity = hugeCapacity(minCapacity);
        //拷贝老数据进入新的数组,完成扩容。
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
    private static int hugeCapacity(int minCapacity) {
        //如果minCapacity小于0报错
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
2.4 ArrayList的 remove()方法
public E remove(int index) {
    // 检查索引是否合法
    rangeCheck(index);

    modCount++;
    E oldValue = elementData(index);
    // 需要移动的元素的个数
    int numMoved = size - index - 1;
    if (numMoved > 0)
        //截取index后面的值复制到index->length-1.
        System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
    // 赋值为空,有利于进行GC
    elementData[--size] = null; 
    // 返回旧值
    return oldValue;
}

你可能感兴趣的:(ArrayList源码分析)