List介面(動態陣列)
阿新 • • 發佈:2020-07-28
List介面(動態陣列)
List集合類中元素有序且可重複
ArrayList(重要)
- 作為List介面的主要實現類
- 執行緒不安全的,效率高
- 底層使用Object[] elementData陣列儲存
ArrayList的原始碼分析
jdk7
- 構造器
ArrayList list = new ArrayList();
- 底層建立了長度為10的Object[]陣列elementData
- 新增資料
list.add(123)
- 相當於elementData[0] = new Integer(123)
- 底層的陣列長度為10,新增元素個數小於10時,正常新增元素
- 新增的元素個數大於10後(底層elementData陣列容量不夠),則需要擴容,預設擴容為原來容量的1.5倍(相當於新造一個數組,長度為原來長度的1.5倍)。同時需要將原來陣列的資料複製到新的陣列中
結論:建議使用帶參的構造器(避免在中間時擴容)
ArrayList list = new ArrayList(int capacity)
jdk8
- 構造器
ArrayList list = new ArrayList();
- 底層Object[] elementData初始化為{},並沒有建立長度為10的陣列
- 新增資料
list.add(123)
- 第一次add()時,底層才建立了長度為10的陣列,並將資料123新增到elementData[0]位置上
- 後續的新增與擴容操作與jdk7相同
結論
- jdk7中的ArrayList的物件的建立類似於單例模式中的餓漢式
- jdk8中的ArrayList的物件的建立類似於單例模式中的懶漢式。延遲了陣列的建立,節省記憶體
LinkedList
- 對於頻繁的插入、刪除操作,使用此類效率比ArrayList高
- 底層使用雙向連結串列儲存
LinkedList的原始碼分析
LinkedList list = new LinkedList();
內部聲明瞭Node型別的first和last屬性,預設值為null
list.add(123);
將123封裝到Node中,建立了Node物件
其中Node定義為(原始碼),體現了LinkedList雙向連結串列的特徵:
private static class Node<E> { E item; LinkedList.Node<E> next; LinkedList.Node<E> prev; Node(LinkedList.Node<E> prev, E element, LinkedList.Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }
Vector(不常用)
- 作為List介面的古老實現類
- 執行緒安全的、效率低
- 底層使用Object[] elementData陣列儲存
Vector原始碼分析
- jdk7和jdk8中通過Vector()構造器建立物件時,底層都建立了長度為10的陣列
- 預設擴容為原來陣列長度的2倍
三者異同
相同點
三個類都實現了List介面,儲存資料的特點相同(有序、可重複的資料)
不同點
- 底層不同
- 不同情況下效率不同
- 執行緒安全問題