Skip to content

ArrayList的源码 ​

  • ArrayList的底层是数组。

目前看源码,比较关心的几个问题

  • ArrayList的初始化容量是10, 但是我们之前看构造方法的时候,没看到。
  • 底层是怎么扩容的?是不是添加一个数据,扩容一次。

ArrayList的初始化逻辑 ​

JAVA
class ArrayList{
    
    // 这个就是ArrayList底层的数组。  
    Object[] elementData;
    
    // 底层实际存储了多少个元素的个数。
    int size;
    
    static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    
    private static final int DEFAULT_CAPACITY = 10;
   
    // 这个是一个空构造方法, 在空构造方法里面,啥也没做,赋了一个常量。
    // 就是个空的。{}。我替大家推测了一下, 空构造里面,啥也没赋值。 ===》  在添加方法的时候,一定得能用。 
    // 所以接下来,我们看 添加方法。 
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    
    // e是要添加的元素。 
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        // 直接往数组的size位置,赋值e。   e其实就是我们要存进去的数据。
        // 所以走到这一行,就说明一个事情, 数组已经初始化好了
        elementData[size++] = e;
        return true;
    }
    
    // minCapacity = 1
    private void ensureCapacityInternal(int minCapacity) {
        // 这里两个方法套在一起,其实是内层方法的返回值作为外层方法的输入值。 
        // 也就是先执行 calculateCapacity(elementData, minCapacity)
        // 再执行这个 ensureExplicitCapacity()
        //                     calculateCapacity它的返回值是10
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    
    //                                             {}                1
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        // 所以,先进入这个方法里。 因为elementData目前确实是它
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            //   DEFAULT_CAPACITY = 10;
            // return Matn.max(10, 1);   返回的是10 
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }
    
    //               ensureExplicitCapacity()    10
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        //  10         -    0   > 0
        if (minCapacity - elementData.length > 0)
            // 索引会进入这个方法。
            grow(minCapacity);
    }
    
    //                      10
    private void grow(int minCapacity) {
        // oldCapacity = 0
        int oldCapacity = elementData.length;
        // newCapacity = 1.5 * oldCapacity = 0
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        
        //   0 - 10  < 0  进入
        if (newCapacity - minCapacity < 0)
            // newCapacity = minCapacity = 10;
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // 拷贝 elementData.  拷贝 10个。 
        // 其实做了一个特殊处理。  如果之前有, ["zs", "ls"]  。拷贝的数目不够,会补null.
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
    
}

扩容逻辑 &#8203;

什么时候会扩容? 所以肯定会在添加数据的时候,进行扩容。

所以要看add方法。

JAVA
class ArrayList{
    
    // 这个就是ArrayList底层的数组。  
    Object[] elementData;
    
    // 底层实际存储了多少个元素的个数。
    int size;
    
    
    // 假设,底层数组是10个。我们这个e已经是第11个数据了。 
    public boolean add(E e) {
        // 扩容一定是在这一行扩的。 
        //                      10  + 1 = 11 
        ensureCapacityInternal(size + 1); 
        elementData[size++] = e;
        return true;
    }
    
    // 											11
    private void ensureCapacityInternal(int minCapacity) {
        // calculateCapacity(elementData, minCapacity) 的返回值是 11
        // ensureExplicitCapacity(11). 入参是11.
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    
    // 									elementData = new Object[10];    , 11
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //     11 
        return minCapacity;
    }
    
    //                                         11
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        //    11   -  10  >  0成立。 进入,
        if (minCapacity - elementData.length > 0)
            // grow(11)
            grow(minCapacity);
    }
    
    
    //                        11
    private void grow(int minCapacity) {
        // oldCapacity = 10
        int oldCapacity = elementData.length;
        // newCapacity = 1.5 * oldCapacity = 15
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        
        //  15 - 11  < 0  不成立。 
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        
        // int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // elementData =  新容量是15。
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
    
    // 总结一下: 咋扩容的。 1.5倍原始容量
}

源码属于一个提高部分。如果听得懂更好,如果听不懂,先放一放。因为不影响后面写代码。

JAVA
class ArrayList{
    
    // 这个就是ArrayList底层的数组。  
    Object[] elementData;
    
    // 底层实际存储了多少个元素的个数。
    int size;
    
    
    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;
    }
    
    
}