Detailed principles underlying ArrayList

Preface:

  • Here I use JDK8

  • Speaking before the ArrayList, will speak simply, under List

  • List ordered set represents a collection, each element has its own set of corresponding sequence index, it inherits the Collection interface, an ordered set may be defined to allow a duplicate

  • List interface features:
    1, with a subscript
    2, sequential
    3, can be repeated

  • List interfaces to achieve the set are:

    • ArrayList、LinkedList、Vector、Stack
  • In this article, only speak in detail underlying ArrayList

ArrayList

  • Implements List interface, and the most common kind of collection
  • Features: the underlying data structure is an array, the query faster, by deleting slow, thread-safe, high efficiency
  • Advantages: High efficiency operation of a read operation, based on the underlying 数组implementation, may be a null value, allowing repeat elements, ordered, asynchronous .
  • Disadvantage: because it is the underlying dynamic array is implemented, is not suitable for frequent insertion and deletion of elements, because each insertion and deletion requires moving elements in the array, slow and complex operation.

The underlying principle

We explain the following code, and enter debug mode from the bottom

import java.util.ArrayList;

public class ArrayListDemo {
    public static void main(String[] args) {
        ArrayList<Integer> arryayList = new ArrayList<Integer>();
        arryayList.add(1);
        arryayList.add(2);
        arryayList.add(3);
        arryayList.add(4);
        arryayList.add(5);
        arryayList.add(6);
        arryayList.add(7);
        arryayList.add(8);
        arryayList.add(9);
        arryayList.add(10);
        arryayList.add(11);
    }
}

We are all marked with the code inside the main method breakpoint
Here Insert Picture Descriptionto enter debug mode, press F7, press F8, press F7, you can skip the class loader into the ArrayList class

  • The method of construction ArrayList

 public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
  1. elementData is an empty Object array,
  2. DEFAULTCAPACITY_EMPTY_ELEMENTDATA: constant is an empty array
1.transient Object[] elementData;
#
2.private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

The first conclusion :
Object [] elementData: ArrayList is where to store data, and the array is empty

ArrayList存储数据的地方其实是一个Object数组,并且一开始是{}(空数组)
     public ArrayList() {
         this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

Then we will add debug into the bottom, the first will enter the package method, which has nothing to do with the underlying, skip, so we jump out press F8, press F7 to enter the
Here Insert Picture Descriptionadd method to jump here

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

size刚开始是等于0 : size=0,

  • 我们再进入ensureCapacityInternal方法
    这里的minCapacity就是size+1
    minCapacity = 1
private void ensureCapacityInternal(int minCapacity) {//minCapacity=1
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    
  • 进入calculateCapacity(elementData, minCapacity)
    elementData:就是Object数组,这里是空数组
    minCapacity = 1
private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

在ArrayList的构造方法中就是
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
所以两者是相等的,会执行

//DEFAULT_CAPACITY=10
//minCapacity = 1
return Math.max(DEFAULT_CAPACITY, minCapacity);//返回DEFAULT_CAPACITY=10

而DEFAULT_CAPACITY =10

 private static final int DEFAULT_CAPACITY = 10;

所以执行的代码如下

return Math.max(10,1);//返回10

那么10就会返回到这里

private void ensureCapacityInternal(int minCapacity) {//minCapacity=1
		//相等于ensureExplicitCapacit(10)
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
  • 进入ensureCapacityInternal方法中
  1. 此时的minCapacity=10
    Here Insert Picture Description
private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

minCapacity=10,
elementData.length = 0
那么必然进行grow(minCapacity)方法中
grow()就是扩容方法

  • 进入grow()方法中
 private void grow(int minCapacity) {//minCapacity=10
        // overflow-conscious code
        int oldCapacity = elementData.length;//oldCapacity是旧的容量为0
        //newCapacity :新容量
        //oldCapacity >> 1:右移一位,位运算,相当于oldCapacity/2
        //newCapacity=旧容量+旧容量的0.5倍 = 1.5倍,所以ArrayList每次扩容1.5倍
        //但在这里newCapacity=0,因为oldCapacity=0
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
  1. int oldCapacity = elementData.length;//oldCapacity是旧的容量为0

  2. newCapacity :新容量

  3. oldCapacity >> 1:右移一位,位运算,相当于oldCapacity / 2

  4. **newCapacity=旧容量+旧容量的0.5倍 = 1.5倍,所以ArrayList每次扩容1.5倍**

  5. newCapacity oldCapacity + = int (oldCapacity >>. 1);
    newCapacity = 0 + (0 >>. 1) = 0
    compliance if (newCapacity - minCapacity <0) is determined statements
    and minCapacity = 10, then give newCapacity = minCapacity = 10;
    a second wrap-up :
    ArrayList每次扩容原来的1.5倍
    Here Insert Picture Description

  • The method then proceeds copyOf,
//original=elementData:就是旧数组
//newLength = newCapacity = 10 //新数组
 public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }
  • There is also a copyOf, then enter

Here Insert Picture DescriptionThe most important array replication method

//将原来的数组,从0开始,复制到copy这个数组中,也是从0开始,复制原来数组的长度
System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));

The original array, starting from 0, copy to copy this array, also starting at 0, copy the original length of the array
is actually a copy of the original data array into a new array

Third summarize:
Arrays.copyOf in the grow () method () is doing the real expansion

Arrays.copyOf(elementData,newCapacity(minCapacity))
   这个方法在做数组的扩容,底层其实就是System.arrayCopy()

And then return to copy the new array, assigned to the old array, thus completing the expansion

 elementData = Arrays.copyOf(elementData, newCapacity);//elementData  = copy

Upon completion of the expansion of add back the original method

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 完成扩容
        //elementData:就是完成扩容后的数组,size++,
        //elementData[1] = e,完成添加操作
        elementData[size++] = e;
        return true;
    }

Source: https://blog.csdn.net/xiannbi
article belongs to all authors, welcome to reprint, but without the author's consent declared by this section must be retained, and given the original connection in the apparent position of the article page, otherwise leave to pursue legal responsibilities right.

Released three original articles · won praise 0 · Views 94

Guess you like

Origin blog.csdn.net/xiannbi/article/details/104551552