Java 集合 — ArrayList

ArrayList

  • ArrayList是基于数组实现的List
  • 是有序的
  • 每次添加之前判断是否进行扩容
  • 不是线程安全的。

构造方法

// 空数组
private static final Object[] EMPTY_ELEMENTDATA = {};

// 簿制定大小的初始化,初始化为一个空数组
public ArrayList() {
	// super 方法为空
    super();
    // 初始化list为一个空数组,在add的ensureCapacityInternal进行初始化
    this.elementData = EMPTY_ELEMENTDATA;
}

public ArrayList(int initialCapacity) {
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
	// 将list初始化为制定大小                                           
    this.elementData = new Object[initialCapacity];
}

// 从一个collection创建一个list
public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    size = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    // http://blog.csdn.net/aitangyong/article/details/30274749
    // 大致意思就是c.toArray返回的不一定是Object[],所以需要进行判断
    if (elementData.getClass() != Object[].class)
    	// 如果不是Object数组复制到一个Object数组
        elementData = Arrays.copyOf(elementData, size, Object[].class);
}

add

在查看add方法之前,先看看ArrayList父类AbstractList的一个属性modCount
protected transient int modCount = 0;
modCount是用来记录list改变的次数(add,remove,addAll etc.),这个值是被Iterator和ListIterator使用,用来检查在遍历list的时候list是否发生变化,也就是是否存在并发访问的情况。如果一个线程在遍历的时候,另一个线程进行add和remove,会造成遍历出错抛出ConcurrentModificationException

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
	// 每次add的时候都会增加modCount
    modCount++;

    // overflow-conscious code
    // 如果原来的数组已经满了,则进行扩容
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

// list扩容
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    // 每次扩容为原来的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
    	// 当一开始数组大小为1的时候会出现,即elementData.length = 1
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
    	// minCapacity可能会溢出,Integer.MAX_VALUE + 1就是负的
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

get

public E get(int index) {
	// 检查数组下标是否越界
    rangeCheck(index);
	// 使用数组下标直接访问
    return elementData(index);
}

set 替换原来index位置的元素

public E set(int index, E element) {
    rangeCheck(index);

    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}

remove

public E remove(int index) {
    rangeCheck(index);
	// 删除的时候也需要对modCount加1,因为modCOunt记录的是list的改变次数,remove也会改变list
    modCount++;
    // 记录下被删除的元素,下面返回
    E oldValue = elementData(index);

    int numMoved = size - index - 1;
    if (numMoved > 0)
    	// copy的时候跳过要删除的元素
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}
posted @ 2016-11-29 23:04  lacker  阅读(300)  评论(0编辑  收藏  举报