Java下位層のArrayList下位層実現原理


ArrayListの概要
ArrayListは動的配列であり、Arrayの複雑なバージョンに相当し、動的な増加と減少要素を提供し、CollectionとListインタフェースを実現し、配列の大きさを柔軟に設定することができる.なお、ArrayListはスレッドセキュリティではないので、一般的には単一スレッドでArrayListを使用することを推奨します.ArrayListの要素はnullであってもよい.
ソース解析
ArrayListの下部には配列格納要素が使用され、デフォルトの配列サイズは10です.
//      
private static final int DEFAULT_CAPACITY = 10;
//      
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

  1. indexOf(Object o)メソッド
    //      ,           
    public int indexOf(Object o) {
        //    null,     null   
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            //    ,             
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        //      -1
        return -1;
    }

  2.LastIndexOf(Object o)メソッド
    //    ,              ,   indexOf  
    public int lastIndexOf(Object o) {
        if (o == null) {
            for (int i = size-1; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {
            //      ,indexOf   
            for (int i = size-1; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

  3.get(int index)メソッド
    //          
    public E get(int index) {
        //        
        rangeCheck(index);
        //         
        return elementData(index);
    }
    private void rangeCheck(int index) {
        //          ,        
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

   4. add(E e)法:配列容量が足りない場合、拡張は元の1.5倍になる
    //    
    public boolean add(E e) {
        //      ,          
        ensureCapacityInternal(size + 1);
        elementData[size++] = e;
        return true;
    }
    private void ensureCapacityInternal(int minCapacity) {
        //     ArrayList     ,     ,minCapacity             minCapacity    
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //        
        ensureExplicitCapacity(minCapacity);
    }
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
         //                  ,    (          ,minCapacity              ,             +1)
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    private void grow(int minCapacity) {
        //     
        int oldCapacity = elementData.length;
        //          +   /2
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        //     
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

   4. set(int index,E element)メソッド:元の位置の要素を置換する
    public E set(int index, E element) {
        //  index          
        rangeCheck(index);
        E oldValue = elementData(index);
        //          
        elementData[index] = element;
        return oldValue;
    }
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

   5.add(int index,E element)メソッド:要素を挿入し、後ろの要素を後ろに移動
   public void add(int index, E element) {
        //        ,  
        rangeCheckForAdd(index);
        //          
        ensureCapacityInternal(size + 1);
        //              ,    
        System.arraycopy(elementData, index, elementData, index + 1,
            size - index);
        //    
        elementData[index] = element;
        size++;
    }

   6.remove(int 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);
        //          null
        elementData[--size] = null;
        return oldValue;
    }