1. 程式人生 > 其它 >List介面常用實現類對比

List介面常用實現類對比

相同點

都實現了List介面 儲存了有序 可重複的資料

不同點

ArrayList

執行緒不安全 但是效率高 底層使用 Object[] elementData 實現

LinkedList

底層使用雙向連結串列資料結構 對於頻繁的插入 刪除 該類比ArrayList效率高

Vector

執行緒安全 但是效率低 底層使用 Object[] elementData 實現

原始碼分析

ArrayList

JDK8ArrayList底層使用Object[] elementData陣列儲存 預設初始化大小10

/**
     * Default initial capacity. 預設初始化容量 10
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
	 * 用於空例項的陣列 即 new ArrayList(0)
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
	 * 用於預設大小的空例項的共享空陣列例項
 	 * 將其與 EMPTY_ELEMENTDATA 區別開來,以便知道何時應該膨脹多少
	 * 新增第一個元素。
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
 
    transient Object[] elementData; // non-private to simplify nested class access
   
    private int size; // 陣列大小

建構函式

public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    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;
        }
    }

有三種建構函式 無參建構函式 有參建構函式(集合型別的建構函式 int型別的建構函式)
ArrayList list = new ArrayList(); 此時呼叫ArrayList無參建構函式 底層Object[] elementData初始化為{} 沒有建立集合大小!!!!!


add方法

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

public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

當例項ArrayList後 得到list物件 此時Object[] elementData初始化為{} 呼叫add方法時
此時容量才被初始化為 10

因為elementData為 {} 長度為 0 沒有達到最低容量要求 必須得擴容了



小結

  1. 只要集合長度沒有達到最小容量 必須得擴容 長度一般是原來的1.5倍(位運算子 >>1 相當於 原來的容量 / 2 + 原來的容量)
  2. ArrayList物件建立類似於 單例模式的懶漢式 延遲了陣列的建立 節省記憶體

LinkedList

LinkedList linkList = new LinkedList();

linkList.add("wwbao");

public boolean add(E e) {
        linkLast(e); // 呼叫linkLast方法 並且將新增的值也傳過去
        return true;
}

示意圖

小結

  1. 雙向連結串列中 第一個節點的prev永遠為 null 最後一個節點的next 永遠為null
  2. 上一個節點的next指向下一個節點 下一個節點的prev指向上一個節點
即使再小的帆也能遠航