Analyze the principle of ArrayList expansion from the perspective of source code

Analyze the principle of ArrayList expansion from the perspective of source code

1. The construction method of ArrayList

Look at the source code first to look at the construction method, we first look at ArrayListthe construction method of, it has three construction methods:

public ArrayList(int initialCapacity);	//传入一个数组的大小
public ArrayList();	//空参构造
public ArrayList(Collection<? extends E> c);	//传入一个Collection集合

For these three construction methods, let's take a look at its source code respectively. Let's take a look at the first one:

    public ArrayList(int initialCapacity) {
    
    
      	//判断大小是否大于0
        if (initialCapacity > 0) {
    
    
          	//大于0则新建一个大小为initialCapacity的Object数组
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
    
    
          	//如果等于0则给它赋值一个空的数组
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
    
    	
          	//小于0则抛异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

For this construction method, first, when is initialCapacitygreater than 0, initialCapacityan Object array of size is created . If it is equal to 0, then it will be assigned to the array EMPTY_ELEMENTDATA, we can take a look at what this EMPTY_ELEMENTDATAis:

private static final Object[] EMPTY_ELEMENTDATA = {
    
    };

In fact, this EMPTY_ELEMENTDATAis an empty array.

Let's take a look at the construction method without parameters:

	public ArrayList() {
    
    
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }	

This parameterless construction method directly assigns one to the array DEFAULTCAPACITY_EMPTY_ELEMENTDATA. In fact, this DEFAULTCAPACITY_EMPTY_ELEMENTDATAis also an empty array. We can look at the definition of the constant in the source code:

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
    
    };

For the third construction method, it is just to Collectionconvert into an array:

    public ArrayList(Collection<? extends E> c) {
    
    
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
    
    
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
    
    
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

2. The add method of ArrayList

After reading the construction method above, we know that if the initialization ArrayListis an empty parameter or the incoming size is 0, an empty array will be initialized ; if it is greater than 0, a new Objectarray of the corresponding size will be created , and then we will Look at the add(E e)method

    public boolean add(E e) {
    
    
      	//扩容关键的一步
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

This method is more critical in this ensureCapacityInternal()method, and the next step is to assign values ​​to him, there is nothing critical. So let's take a look at this ensureCapacityInternal(size+1)method.

    private void ensureCapacityInternal(int minCapacity) {
    
    
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

This method calls two methods, one is calculateCapacity(Object[] elementData, int minCapacity), the other is ensureExplicitCapacity, let’s take a look at the calculateCapacity(Object[] elementData, int minCapacity)method in parentheses :

    private static int calculateCapacity(Object[] elementData, int minCapacity) {
    
    
      	//如果是空数组
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    
    
          	//private static final int DEFAULT_CAPACITY = 10;
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
      	//不为空则返回minCapacity
        return minCapacity;
    }

We can see that this method is a method to calculate the capacity of the array, and what is passed in minCapacityis add()the size of the inserted array passed in the method. When the array is empty (that is, when we passed in a null parameter or 0) Math.max(默认大小, minCapacity), even if the maximum value of the default size and the minimum capacity required by the array is taken. ; If it is not empty, it returns directly.

Let's look at the ensureExplicitCapacitymethod:

    private void ensureExplicitCapacity(int minCapacity) {
    
    
        modCount++;

        // 如果数组所需的最小容量 > 数组的长度
        if (minCapacity - elementData.length > 0)
          	//扩容
            grow(minCapacity);
    }

It can be seen that if the minimum capacity required by the array is greater than the length of the array, ArrayListit will expand, and then look at the growmethod:

    private void grow(int minCapacity) {
    
    
        // 获取当前数组的长度
        int oldCapacity = elementData.length;
      
      	//oldCapacity >> 1 = oldCapacity/2,即使oldCapacity + oldCapacity/2。
      	//增加了原来的一半,即扩容后是原来的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
      	//如果扩容后还小于所需的容量
        if (newCapacity - minCapacity < 0)
          	//直接将所需容量复制给新的大小
            newCapacity = minCapacity;
      	//如果扩容后的大小大于最大值
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // 把老数组copy到新数组中
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

So there are three main steps in this expansion function:

  • Increased by half, that is, 1.5 times the original after expansion
  • If the capacity is still less than the required capacity after expansion, then directly change the capacity to the required minimum capacity
  • Copy the old array to the new array

3. Summary

In summary:

  • When initializing ArrayList, if the initial size is specified, then the Objectarray of the corresponding size is initialized ; if the size is not specified, the empty array is initialized, and the default size is 10.
  • When expanding, it increases by half, that is, the expanded size is 1.5 times the original.

Guess you like

Origin blog.csdn.net/qq_14810195/article/details/107835008