ArrayList和LinkedList的區別

2022-08-20 04:30:26 字數 3407 閱讀 3513

arraylist和linkedlist使用了陣列的實現。可以認為arraylist或者vector封裝了對內部陣列的操作,比如向陣列中新增,刪除,插入新的元素或者資料的擴充套件和重定向。

linkedlist使用了迴圈雙向鍊錶資料結構。與基於陣列arraylist相比,這是兩種截然不同的實現技術,這也決定了它們將適用於完全不同的工作場景。

linkedlist鍊錶由一系列表項連線而成。乙個表項總是包含3個部分:元素內容,前驅表和後驅表。如下圖所示:

在下圖展示了乙個包含3個元素的linkedlist的各個表項間的連線關係。在jdk的實現中,無論likedlist是否為空,鍊錶內部都有乙個header表項,它既表示鍊錶的開始,也表示鍊錶的結尾。

表項header的後驅表項便是鍊錶中第乙個元素,表項header的前驅表項便是鍊錶中最後乙個元素。

下面以增加和刪除元素為例比較arraylist和linkedlist的不同之處:

(1)增加元素到列表尾端:

在arraylist中增加元素到佇列尾端的**如下:

public boolean add(e e)
arraylist中add()方法的效能決定於ensurecapacity()方法。ensurecapacity()的實現如下:

public vod ensurecapacity(int mincapacity)

其中addbefore()的方法實現如下:private entryaddbefore(e e,entryentry)

可見,linkelist由於使用了鍊錶的結構,因此不需要維護容量的大小。從這點上說,它比arraylist有一定的效能優勢,然而,每次的元素增加都需要新建乙個entry物件,並進行更多的賦值操作。

在頻繁的系統呼叫中,對效能會產生一定的影響。

(2)增加元素到列表任意位置

除了提供元素到list的尾端,list介面還提供了在任意位置插入元素的方法:void add(int index,e element);

由於實現的不同,arraylist和linkedlist在這個方法上存在一定的效能差異,由於arraylist是基於陣列實現的,而陣列是一塊連續的記憶體空間,如果在陣列的任意位置插入元素,必然導致在該位置後的所有元素需要重新排列,因此,其效率相對會比較低。

以下**是arraylist中的實現:

public void add(int index,e element)

可以看到每次插入操作,都會進行一次陣列複製。而這個操作在增加元素到list尾端的時候是不存在的,大量的陣列重組操作會導致系統效能低下。並且插入元素在list中的位置越是靠前,陣列重組的開銷也越大。

而linkedlist此時顯示了優勢:

public void add(int index,e element)

可見,對linkedlist來說,在list的尾端插入資料與在任意位置插入資料是一樣的,不會因為插入的位置靠前而導致插入的方法效能降低。

(3)刪除任意位置元素

對於元素的刪除,list介面提供了在任意位置刪除元素的方法:

public e remove(int index);

對arraylist來說,remove()方法和add()方法是雷同的。在任意位置移除元素後,都要進行陣列的重組。arraylist的實現如下:

public e remove(int index)

可以看到,在arraylist的每一次有效的元素刪除操作後,都要進行陣列的重組。並且刪除的位置越靠前,陣列重組時的開銷越大。

public e remove(int index)

private entryentry(int index)else

return e;

}在linkedlist的實現中,首先要通過迴圈找到要刪除的元素。如果要刪除的位置處於list的前半段,則從前往後找;若其位置處於後半段,則從後往前找。因此無論要刪除較為靠前或者靠後的元素都是非常高效的;但要移除list中間的元素卻幾乎要遍歷完半個list,在list擁有大量元素的情況下,效率很低。

(4)容量引數

容量引數是arraylist和vector等基於陣列的list的特有效能引數。它表示初始化的陣列大小。當arraylist所儲存的元素數量超過其已有大小時。它便會進行擴容,陣列的擴容會導致整個陣列進行一次記憶體複製。因此合理的陣列大小有助於減少陣列擴容的次數,從而提高系統效能。

public arraylist()

public arraylist (int initialcapacity)

arraylist提供了乙個可以制定初始陣列大小的建構函式:

public arraylist(int initialcapacity)

現以構造乙個擁有100萬元素的list為例,當使用預設初始化大小時,其消耗的相對時間為125ms左右,當直接制定陣列大小為100萬時,構造相同的arraylist僅相對耗時16ms。

(5)遍歷列表

遍歷列表操作是最常用的列表操作之一,在jdk1.5之後,至少有3中常用的列表遍歷方式:foreach操作,迭代器和for迴圈。

string tmp;

long start=system.currenttimemills(); //foreach

for(string s:list)

system.out.println("foreach spend:"+(system.currenttimemills()-start));

start = system.currenttimemills();

for(iteratorit=list.iterator();it.hasnext();)

system.out.println("iterator spend;"+(system.currenttimemills()-start));

start=system.currenttimemills();

int size=;list.size();

for(int i=0;i構造乙個擁有100萬資料的arraylist和等價的linkedlist,使用以上**進行測試,測試結果的相對耗時如下表所示: 

可以看到,最簡便的foreach迴圈並沒有很好的效能表現,綜合性能不如普通的迭代器,而是用for迴圈通過隨機訪問遍歷列表時,arraylist表項很好,但是linkedlist的表現卻無法讓人接受,

甚至沒有辦法等待程式的結束。這是因為對linkedlist進行隨機訪問時,總會進行一次列表的遍歷操作。效能非常差,應避免使用。

Array List和ArrayList的區別與

定義 public abstract class array icloneable,ilist,icollection,ienumerable,istructuralcomparable,istructuraequatable 陣列在記憶體中是連續儲存的,所以它的索引速度是非常的快,而且賦值與修改元...

LinkedList和ArrayList的區別

對於集合collection下的list介面,有兩個實現類,arraylist和linkedlist,那麼他們兩個有什麼區別呢。arraylist的底層由陣列實現,而linkedlist的底層由雙向鍊錶實現,底層的不同才是他們區別的根源。然而因為他們繼承於同乙個父介面,他們的很多方法都是相同的。關於...

ArrayList和LinkedList的面試題

一 arraylist為什麼是執行緒不安全的?arraylist在新增乙個元素的時候,它可能會有兩步來完成 1.在 items size 的位置存放此元素 2.增大 size 的值。在單執行緒執行的情況下,如果 size 0,新增乙個元素後,此元素在位置 0,而且 size 1 而如果是在多執行緒情...