Java学习笔记Java 杂谈技术文

Java源码分析-ArrayList

2016-10-05  本文已影响86人  gatsby_dhn

ArrayList是我们最常用的集合类,我们看下它的实现(基于JDK1.8)。

支持原创,转载请注明出处。

继承关系

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

public interface List<E> extends Collection<E>

ArrayList实现了List接口,List又实现了Collection接口。

核心成员变量

    private static final int DEFAULT_CAPACITY = 10 ;   //默认容量
    transient Object [] elementData;                   //保存元素
    private int size ;                                 //当前元素个数
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //空数组

我们注意,数组默认的大小为10。

构造函数

    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() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }  //初始化一个空数组

添加元素

    public boolean add(E e) {      //在最后添加元素
        ensureCapacityInternal(size + 1);  //确保不会越界
        elementData[size++] = e;          //加入数组
        return true;
    }

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

        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);    //扩容机制
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        //拷贝原始数组到一个新的数组,新的数组大小为newCapacity,可能截断,或在尾部添加null
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

加入元素e后,首先确保添加该元素后不会溢出,必要时会进行扩容,扩容机制为int newCapacity = oldCapacity + (oldCapacity >> 1)大约为原大小的1.5倍,然后将原数组复制到新的长度为newCapacity的数组中。最后将该元素e加入到数组末尾。这里我们看到根据需要指定ArrayList的大小可以防止扩容,提高效率。

查找元素

   public E get(int index) {
        rangeCheck(index);    //检查是否越界

        return elementData(
    }

    E elementData(int index) {
        return (E) elementData[index];     //返回对应下标的元素
    }

查找很简单,先检查是否越界,不越界就返回对象下标的元素。

删除元素

    public E remove(int index) {
        rangeCheck(index);    //越界检查

        modCount++;
        E oldValue = elementData(index);   //保存要删除的元素

        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

        return oldValue;   //返回被删除元素
    }

在数组中间删除元素同样会进行拷贝,如果是常用操作可以使用LinkedList代替。

支持原创,转载请注明出处。
github:https://github.com/gatsbydhn

上一篇下一篇

猜你喜欢

热点阅读