ArrayList與LinkList對比

前邊兩篇博文簡要總結了一下ArrayListLinkedList的用法以及源碼。本文簡要總結一下這二者的區別,這在面試中也是常常會問到的一個知識點。

先來看一下ArrayList和LinkedList的關係是怎樣的:

從繼承體系可以看到,ArrayList與LinkedList都是Collection接口下List接口的實現類。可謂是一對雙胞胎。

但由於底層數據結構的不同導致ArrayList與LinkedList有本質上的區別。

ArrayList與LinkedList的區別

ArrayList:

 ArrayList是基於動態數組的數據結構。

因爲是數組,所以ArrayList在初始化的時候,有初始大小10,插入新元素的時候,會判斷是否需要擴容,擴容的步長是0.5倍原容

量,擴容方式是利用數組的複製,因此有一定的開銷;

另外,ArrayList在進行元素插入的時候,需要移動插入位置之後的所有元素,位置越靠前,需要位移的元素越多,開銷越大,相

反,插入位置越靠後的話,開銷就越小了,如果在最後面進行插入,那就不需要進行位移;

LinkedList:

內部使用基於鏈表的數據結構實現存儲,LinkedList有一個內部類作爲存放元素的單元,裏面有三個屬性,用來存放元素本身以及

前後2個單元的引用,另外LinkedList內部還有一個header屬性,用來標識起始位置,LinkedList的第一個單元和最後一個單元都會指向

header,因此形成了一個雙向的鏈表結構。

LinkedList是採用雙向鏈表實現的。所以它也具有鏈表的特點,每一個元素(結點)的地址不連續,通過引用找到當前結點的上一

個結點和下一個結點,即插入和刪除效率較高,只需要常數時間,而get和set則較爲低效。

LinkedList的方法和使用和ArrayList大致相同,由於LinkedList是鏈表實現的,所以額外提供了在頭部和尾部添加/刪除元素的方

法,也沒有ArrayList擴容的問題了。另外,ArrayList和LinkedList都可以實現棧、隊列等數據結構,但LinkedList本身實現了隊列的接

口,所以更推薦用LinkedList來實現隊列和棧。

 

總而言之,ArrayList和LinkedList的區別有以下幾點:

  •  ArrayList是實現了基於動態數組的數據結構,而LinkedList是基於鏈表的數據結構;
  • 對於隨機訪問元素,Array獲取數據的時間複雜度是O(1),但是要刪除數據卻是開銷很大的,因爲這需要重排數組中的所有數據。ArrayList想要get(int index)元素時,直接返回index位置上的元素,而LinkedList需要通過for循環進行查找,雖然LinkedList已經在查找方法上做了優化,比如index < size / 2,則從左邊開始查找,反之從右邊開始查找,但是還是比ArrayList要慢。
  •  對於添加和刪除操作add和remove,LinkedList是更快的。因爲LinkedList不像ArrayList一樣,不需要改變數組的大小,也不需要在數組裝滿的時候要將所有的數據重新裝入一個新的數組,這是ArrayList最壞的一種情況,時間複雜度是O(n),而LinkedList中插入或刪除的時間複雜度僅爲O(1)。ArrayList在插入數據時還需要更新索引(除了插入數組的尾部)。 ArrayList想要在指定位置插入或刪除元素時,主要耗時的是System.arraycopy動作,會移動index後面所有的元素;LinkedList主耗時的是要先通過for循環找到index,然後直接插入或刪除。這就導致了兩者並非一定誰快誰慢。

 

適用場景

很多場景下都是ArrayList更受歡迎。但有些情況下LinkedList更爲合適,比如:

1) 你的應用不會隨機訪問數據。因爲如果你需要LinkedList中的第n個元素的時候,你需要從第一個元素順序數到第n個數據,然後讀取數據。

2) 你的應用有更多的插入和刪除元素操作,更少的讀取數據。因爲插入和刪除元素不涉及重排數據,所以它要比ArrayList要快。

 

以上就是關於ArrayList和LinkedList的差別。你需要一個不同步的基於索引的數據訪問時,請儘量使用ArrayList。ArrayList很快,也很容易使用。但是要記得要給定一個合適的初始大小,儘可能的減少更改數組的大小。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章