您的位置:首页 > 编程语言 > Java开发

Java ArrayList部分源码研究

2018-01-12 22:17 239 查看
/*
今天晚上看了会ArrayList源码,研究了一下主要的函数。主要有以下几个函数:
add()
remove()
ensureCapacity()
grow()
hugeCapacity()
fastremove() (和remove稍有区别)
以及内部类Itr 实现了Iterator接口
基本分析写在注释里了。
*/
public class ArrayList<E> extends AbstractList<E>
 implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    public ArrayList(int initialCapacity) {
        // 如果指定大小,则new一个指定大小的数组
        // 否则elementData为一个Oject类型的空数组(Oject[] EMPTY_ELEMENTDATA = {})
        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() {
        // 不传入任何参数,默认为空数组
        // Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    // 通常size < elementData.length
    // 去掉数组多余部分以减少需要存储的空间
    public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

    public void ensureCapacity(int minCapacity) {
        // 不是默认空数组则为0,否则为10
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            // any size if not default element table
            ? 0
            // larger than default for default empty table. It's already
            // supposed to be at default size.
            : DEFAULT_CAPACITY;

        // 如果传入参数大于minExpand,则增加容量,否则不增加
        if (minCapacity > minExpand) {
            ensureExplicitCapacity(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);    // 默认新容量是旧容量的1.5倍
        if (newCapacity - minCapacity < 0)        // 如果新容量还是满足不了指定容量
            newCapacity = minCapacity;            // 则取所要需求的容量
        if (newCapacity - MAX_ARRAY_SIZE > 0)    // 如果超过数组最大长度
            // hugeCapacity中,如果minCapacity为负数,表明整型溢出,抛出OOM
            // 大于MAX_ARRAY_SIZE则取Integer.MAX_VALUE否则取MAX_ARRAY_SIZE
            // 当 newCapcity = (oldCapacity + (oldCapacity >> 1)) > MAX_ARRAY_SIZE
            //        && minCapacity < 0 时发生
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    public boolean add(E e) {
        // 默认往后添加元素
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

    public void add(int index, E element) {
        // 在指定下表增加元素
        // 越界检查
        rangeCheckForAdd(index);
        // 确保有size+1的容量,ensureCapacityInternal会调用ensureExplicitCapacity
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        // 将原数组index下标开始的元素复制到从index+1开始,也就是往后移,空出index下标位置
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

    public E remove(int index) {
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index); // 旧值

        int numMoved = size - index - 1;
        if (numMoved > 0)
            // 将index位置之后的元素往前移动
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        // 原本的最后一个设置成空,jvm会回收该空间
        elementData[--size] = null; // clear to let GC do its work
        // 返回旧值
        return oldValue;
    }

    public boolean remove(Object o) {
        // 区分空和不空,需要一次循环
        // == 和 equals
        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) {
        // 和remove不同的地方就是不反回旧值且不进行越界检查
        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
    }

    // 内部类Itr实现了Iterator接口
    private class Itr implements Iterator<E> {
        int cursor;       // 迭代器中,指向当前元素的游标
        int lastRet = -1; // 最后一次返回元素的下标,初始为-1
        int expectedModCount = modCount;    // 修改次数

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            // 如果在使用迭代器的过程中,用了ArrayList的修改操作,则会导致迭代器失效
            // 因为ArrayList的add,remove操作会使得modCount++,使得modCount!=expectedModCount
            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];
        }

        public void remove() {
            // 在第一次使用next后才能进行remove
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;    // 使用迭代器的remove不会造成迭代器失效
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

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

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: