ArrayList & LinkedList原始碼解析

wwbao發表於2021-10-10

本文記錄ArrayList & LinkedList原始碼解析 基於JDK1.8

ArrayList

ArrayList實現了List介面 所有擁有List介面所有方法 可以看成可'調節'的陣列 可以包含任何型別資料(包括null,可重複)ArrayList執行緒不是安全的

類結構

ArrayList類主要成員變數:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final long serialVersionUID = 8683452581122892189L;

  	// 初始化容量(陣列初始長度) 10
    private static final int DEFAULT_CAPACITY = 10;

	// 表示空陣列
    private static final Object[] EMPTY_ELEMENTDATA = {};

  	// 也是空陣列,和EMPTY_ELEMENTDATA區分開
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    // 裝ArrayList的陣列
    transient Object[] elementData; // non-private to simplify nested class access

	// 陣列長度
    private int size;
}

方法解析

建構函式

public ArrayList()

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


public ArrayList(int initialCapacity)

public ArrayList(int initialCapacity) {
		// initialCapacity初始化容量 由呼叫者傳入
	
		// 如果initialCapacity大於0
        if (initialCapacity > 0) {
			// elementData為 Object型別的  initialCapacity大小的陣列
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
			// 如果初始值為0 elementData為 EMPTY_ELEMENTDATA 空陣列
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
			// initialCapacity 小於0  拋錯
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
}

public ArrayList(Collection<? extends E> c)

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

建立一個包含指定集合c資料的ArrayList 上面為什麼要多此一舉使用
Arrays.copyOf(elementData, size, Object[].class)複製一遍陣列呢?這是因為在某些情況下
呼叫集合的toArray()方法返回的型別並不是Object[].class 比如:

Long[] array1 = {1L, 2L};
List<Long> list1 = Arrays.asList(array1);
Object[] array2 = list1.toArray();
System.out.println(array2.getClass() == Object[].class); // false

List<Long> list2 = new ArrayList<>();
System.out.println(list2.toArray().getClass() == Object[].class); // true

add方法
add(E e)向陣列尾部新增元素

public boolean add(E e) {
		// 確定陣列容量 size 型別為int 預設值(即初始值)為 0 
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
}


private void ensureCapacityInternal(int minCapacity) {
		// minCapacity = size + 1 = 1    
		// elementData = {}
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}


private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
			// Math.max返回最大的陣列  DEFAULT_CAPACITY = 10   minCapacity = 1 返回 10
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
}


private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
		
        // minCapacity = 10  
		// elementData = {}
  		// 10 - 0 > 0
        if (minCapacity - elementData.length > 0)
			// 擴容
            grow(minCapacity);
}


private void grow(int minCapacity) {
        // oldCapacity = 0
        int oldCapacity = elementData.length;
		// >> 右移運算子 相當於newCapacity為oldCapacity的1.5倍 
		// oldCapacity / 2 此處 0 + 0 / 2 還是等於 0 
        int newCapacity = oldCapacity + (oldCapacity >> 1);
		// newCapacity = 0  minCapacity = 10  0 - 10 < 0 條件成立
        if (newCapacity - minCapacity < 0)
			// newCapacity = 10
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
		// // 複製到新陣列 陣列容量為10
        elementData = Arrays.copyOf(elementData, newCapacity);
 }

private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
		// MAX_ARRAY_SIZE常量值為Integer.MAX_VALUE - 8 通過
    	// 這段邏輯我們可以知道,ArrayList最大容量為Integer.MAX_VALUE
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
}    

綜述 可以知道

  1. 任何一個空的陣列 第一次新增元素的時候 內部陣列容量將被擴容為10
  2. 擴容時,newCapacity為oldCapacity的1.5倍
  3. 容量最大值為Integer.MAX_VALUE - 8
  4. 尾部新增元素不用移動任何元素 所以速度快

相關文章