ArrayList
和LinkedList
是Java集合框架中經常使用的類。如果你只知道從基本性能比較ArrayList
和LinkedList,
那么請仔細閱讀這篇文章。
ArrayList
應該在需要更多搜索操作的地方使用,並且LinkedList
應該在需要更多插入和刪除操作的地方使用。”
ArrayList
使用 Array
數據結構,LinkedList使用 DoublyLinkedList
數據結構。在這里,我們要討論基礎數據結構如何影響插入,搜索的性能,以及刪除操作 ArrayList
和 LinkedList
。
下面是使用ArrayList和LinkedList不同操作的示例:
下面我們將比較
ArrayList和
LinkedList的操作,看哪一個在性能方面更有效。
在最后索引處插入值(塊1和2)
當我們在最后一個索引處插入一個值時,ArrayList必須 :
- 檢查基礎數組是否已滿。
- 如果數組已滿,則將數據從舊數組復制到新數組(大小比舊數組大兩倍),
- 然后在最后一個索引處添加值。
另一方面,LinkedList只是在底層DoublyLinkedList的尾部添加該值。
兩者都具有時間復雜度O(1),但是由於在ArrayList中創建新數組的附加步驟,其最壞情況復雜度達到N的順序,這就是為什么我們更喜歡使用LinkedList.
在給定指數處插入值(第3和第4塊)
當我們在給定索引處插入值時,ArrayList必須 :
- 檢查基礎數組是否已滿。
- 如果數組已滿,則將數據從舊數組復制到新數組(大小為舊數組的兩倍)。
- 之后,從給定索引開始,將值移動一個索引以為新值創建空間。
- 然后在給定索引處添加值。
另一方面,LinkedList只是通過重新排列底層DoublyLinkedList的指針來查找索引並在給定索引處添加該值。
兩者都具有時間復雜度O(N),但是由於在ArrayList中創建新數組並將現有值復制到新索引的附加步驟,我們更喜歡使用LinkedList.
按值搜索(第5和第6塊)
當我們在ArrayList或LinkedList中搜索任何值時,我們必須遍歷所有元素。該操作具有O(N)時間復雜度。看起來像ArrayList和LinkedList都具有相同的性能。
這里我們需要注意的是,數組(ArrayList的底層數據結構)將所有值存儲在連續的內存位置,但是DoublyLinkedList將每個節點存儲在一個隨機的內存位置。迭代連續內存位置比隨機內存位置更具性能效率,這就是為什么我們在按值搜索時更喜歡使用LinkedList而不是LinkedList。
按索引獲取元素(第7和第8塊)
當我們通過Index獲得元素時,ArrayList是一個明顯效果更好。
ArrayList可以為您提供O(1)復雜度的任何元素,因為該數組具有隨機訪問屬性。您可以直接訪問任何索引而無需遍歷整個數組。
LinkedList具有順序訪問屬性。它需要迭代每個元素以達到給定的索引,因此從LinkedList通過索引獲取值的時間復雜度是O(N)。
按值刪除(塊9和10)
它類似於在給定索引處添加值。要在ArrayList和LinkedList中按值刪除元素,我們需要迭代每個元素以到達該索引,然后刪除該值。該操作具有O(N)復雜度。
不同的是,要從LinkedList中刪除一個元素,我們只需要修改指針,但是在ArrayList中,我們需要在刪除值的索引之后移動所有元素以填充創建的間隙。
由於移位是昂貴的操作然后修改指針,因此即使在相同的總體復雜度O(N)之后,我們更喜歡LinkedList,其中需要更多按值操作刪除。
按索引刪除(第11和12欄)
為了通過索引刪除,ArrayList使用O(1)復雜度中的隨機訪問來查找該索引,但是在移除元素之后,移位其余元素會導致整體O(N)時間復雜度。
另一方面,LinkedList花費O(N)時間來使用順序訪問來查找索引,但是要刪除元素,我們只需要修改指針。
由於移位是比迭代更昂貴的操作,因此如果我們想要逐個刪除元素,LinkedList會更有效。