Java集合ArrayList和LinkedList區別

Java的集合類主要由兩個接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口。

Java集合大致可以分爲Set、List、Queue和Map四種體系,其中Set代表無序、不可重複的集合;List代表有序、重複的集合;而Map則代表具有映射關係的集合;Queue體系集合,代表一種隊列集合實現。

jdk1.4以前沒有Queue集合,一般用LinkedList 實現隊列。

集合框架

基礎知識 

數組:

鏈表: 

數組的優點

  1. 隨機訪問性強
  2. 查找速度快

數組的缺點

  1. 插入和刪除效率低,必須移動數組
  2. 可能浪費內存
  3. 內存空間要求高,必須有足夠的連續內存空間。
  4. 數組大小固定,不能動態拓展

鏈表的優點

  1. 插入刪除速度快,只需通過指針指向對象地址
  2. 內存利用率高,不會浪費內存
  3. 大小沒有固定,拓展很靈活

鏈表的缺點

  1. 不能隨機查找,必須從第一個開始遍歷,查找效率低

ArrayList和LinkedList區別

ArrayList和LinkedList的大致區別: 

  1. ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構。 (LinkedList是雙向鏈表,有next也有previous)
  2. 對於隨機訪問get和set,ArrayList覺得優於LinkedList,因爲LinkedList要移動指針。 
  3. 對於新增和刪除操作add和remove,LinedList比較佔優勢,因爲ArrayList要移動數據。 

一.時間複雜度

ArrayList的內部實現是基於基礎的對象數組的,因此,它使用get方法訪問列表中的任意一個元素時(random access),它的速度要比LinkedList快。LinkedList中的get方法是按照順序從列表的一端開始檢查,直到另外一端。對LinkedList而言,訪問列表中的某個指定元素沒有更快的方法。 

例子:我們有一個很大的列表,它裏面的元素已經排好序了,這個列表可能是ArrayList類型的也可能是LinkedList類型的,現在我們對這個列表來進行二分查找(binary search),比較列表是ArrayList和LinkedList時的查詢速度,比較結果ArrayList的時間要明顯小於LinkedList的時間。因此在這種情況下不宜用LinkedList。二分查找法使用的隨機訪問(random access)策略,而LinkedList是不支持快速的隨機訪問的。對一個LinkedList做隨機訪問所消耗的時間與這個list的大小是成比例的。而相應的,在ArrayList中進行隨機訪問所消耗的時間是固定的。 

這是否表明ArrayList總是比LinkedList性能要好呢?這並不一定,在某些情況下LinkedList的表現要優於ArrayList,有些算法在LinkedList中實現時效率更高。比方說,利用Collections.reverse方法對列表進行反轉時,其性能就要好些。

例子:要對其進行大量的插入和刪除操作,在這種情況下LinkedList就是一個較好的選擇。請看如下一個極端的例子,我們重複的在一個列表的開端插入一個元素,ArrayList耗時比LinkList長。當一個元素被加到ArrayList的最開端時,所有已經存在的元素都會後移,這就意味着數據移動和複製上的開銷。相反的,將一個元素加到LinkedList的最開端只是簡單的未這個元素分配一個記錄,然後調整兩個連接。在LinkedList的開端增加一個元素的開銷是固定的,而在ArrayList的開端增加一個元素的開銷是與ArrayList的大小成比例的。

二.空間複雜度 

private static class Entry {   
         Object element;   
         Entry next;   
         Entry previous;   
     } 

LinkedList中有一個私有的內部類Entry,每個Entry對象reference列表中的一個元素,同時還有在LinkedList中它的上一個元素和下一個元素(雙向鏈表)。一個有1000個元素的LinkedList對象將有1000個鏈接在一起的Entry對象,每個對象都對應於列表中的一個元素。這樣的話,在一個LinkedList結構中將有一個很大的空間開銷,因爲它要存儲這1000個Entity對象的相關信息。 

ArrayList使用一個內置的數組來存儲元素,這個數組的起始容量是10。當數組需要增長時,新的容量按如下公式獲得:新容量=(舊容量*3)/2+1,也就是說每一次容量大概會增長50%。這就意味着,如果你有一個包含大量元素的ArrayList對象,那麼最終將有很大的空間會被浪費掉,這個浪費是由ArrayList的工作方式本身造成的。如果沒有足夠的空間來存放新的元素,數組將不得不被重新進行分配以便能夠增加新的元素。對數組進行重新分配,將會導致性能急劇下降。如果我們知道一個ArrayList將會有多少個元素,我們可以通過構造方法來指定容量。我們還可以通過trimToSize方法在ArrayList分配完畢之後去掉浪費掉的空間。

三.總結 

ArrayList和LinkedList在性能上各有優缺點,都有各自所適用的地方,總的說來可以描述如下: 

  1. 對ArrayList和LinkedList而言,在列表末尾增加一個元素所花的開銷都是固定的。對ArrayList而言,主要是在內部數組中增加一項,指向所添加的元素,偶爾可能會導致對數組重新進行分配;而對LinkedList而言,這個開銷是統一的,分配一個內部Entry對象。
  2. 在ArrayList的中間插入或刪除一個元素意味着這個列表中剩餘的元素都會被移動;而在LinkedList的中間插入或刪除一個元素的開銷是固定的。
  3. LinkedList不支持高效的隨機元素訪問。
  4. ArrayList的空間浪費主要體現在在list列表的結尾預留一定的容量空間,而LinkedList的空間花費則體現在它的每一個元素都需要消耗相當的空間

可以這樣說:當操作是在一列數據的後面添加數據而不是在前面或中間,並且需要隨機地訪問其中的元素時,使用ArrayList會提供比較好的性能;當你的操作是在一列數據的前面或中間添加或刪除數據,並且按照順序訪問其中的元素時,就應該使用LinkedList了,這種順序訪問是不是很像隊列操作方式,LinkedList適合實現隊列。

 

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