Java ArrayList源码剖析、fail-fast机制

所在包

java.util

继承关系:

ArrayList<E> extends AbstractList<E>
AbstractList<E> extends AbstractCollection<E>
AbstractCollection<E> extends Object

实现接口

Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAcess

说明:
该类为非同步类,如果存在多个线程读,至少一个线程结构化修改(modifies the list structurally指的是添加删除操作或者resize操作,不包括设置元素值)的情况,需要添加锁操作,或者使用Collections.synchronizedList方法:

List list = Collections.synchronizedList(new ArrayList(...));

关键成员变量:

private static final int DEFAULT_CAPACITY = 10; //数组的初始默认存储容量,初始可以容纳10个元素
private int size; //数组的大小,即所存储的元素个数
protected transient int modCount = 0; /*父类AbstractList成员变量;
表示(structurally modified)修改次数;
用于iterator()和listIterator()方法,如果该值发生非预料变化,相应方法会抛出ConcurrentModificationException异常*/
private static final Object[] EMPTY_ELEMENTDATA = {}; //注意此变量为static类成员
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData; //存储元素的数组

构造方法:

  • 指定初始容量构造,如果指定容量为0,elmentdata指向类成员变量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);
        }
    }
  • 无参构造函数,初始容量为10的空列表
public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
  • 以集合类为参数构造
    示例:
ArrayList<Integer> list1 = new ArrayList();
list1.add(1);
list1.add(2);
ArrayLIst<Integer> res = new ArrayList(list1); //参数为一个集合实现类 res的元素为1,2

扩容操作

添加元素时,会确保有容纳新元素的位置(方法调用add >> ensureCapacityInternal(int minCapacity) >> ensureExplicitCapacity(int minCapacity) >>grow(int minCapacity)),再添加新元素;

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            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
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

fail-fast机制:

if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own removeor add methods, the iterator will throw a ConcurrentModificationException Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
先上代码(以next方法为例):

private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        Itr() {}

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

expectedModCount成员初始值为modCount,迭代器每次next的时候,会调用checkForComodification方法,判断modCount是否有修改,如果有的话就会抛出ConcurrentModificationException异常。所以并发修改arrayLIst实例时,迭代器方法会快速失败,抛出异常。而不是冒险继续非确定的行为。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容