ArrayList和LinkedList的比較

2021-08-07 17:21:52 字數 4473 閱讀 9577

arraylist是基於動態陣列的資料結構,linkedlist是基於鍊錶的資料結構。

下面來分析它們的原始碼,比較一下兩者之間的不同。以下分析基於oracle jdk1.8。

無參構造

private

static

final object defaultcapacity_empty_elementdata = new object[0];

public

arraylist()

初始化了乙個大小為0的object型別的陣列。

有參構造

private

static

final object empty_elementdata = new object[0];

public

arraylist(int var1) else

this.elementdata = empty_elementdata;

}}

初始化了乙個大小指定的object型別的陣列。

由此可見,確實,arraylist維護了乙個陣列

public

void

add(int var1, e var2)

第一步this.rangecheckforadd(var1)是去檢查索引的正確性:

private

void

rangecheckforadd(int var1)

}

超出正常的範圍,就丟擲索引越界異常

第二步this.ensurecapacityinternal(this.size + 1)是去檢查陣列的容量:

private

void

ensurecapacityinternal(int var1)

this.ensureexplicitcapacity(var1);

}

ensurecapacityinternal()中可以看出,陣列預設的最小容量是10。

然後進入ensureexplicitcapacity(),檢查陣列是否需要擴容

private

void

ensureexplicitcapacity(int var1)

}

如果要現在要插入的位置不在陣列大小的範圍內,就需要擴容,進入grow()

private

void

grow(int var1)

if(var3 - 2147483639 > 0)

this.elementdata = arrays.copyof(this.elementdata, var3);

}

正常情況下,通過int var3 = var2 + (var2 >> 1)這一步,定義了新陣列的大小為原來的1.5倍,最後this.elementdata = arrays.copyof(this.elementdata, var3)把原來的陣列拷貝到新的陣列。

回到add(int var1, e var2)

第三步system.arraycopy(this.elementdata, var1, this.elementdata, var1 + 1, this.size - var1)做的操作是其實也是拷貝陣列,只不過是把元素拷貝給自己,實際上就是將插入點之後(也包括插入點)的元素往後移動一位。

後面兩步操作就很容易懂了,就是將插入點原來的元素替換為現在要插入的元素,並且將集合的大小+1。

這裡就介紹一種方法add(int var1, e var2),其他add()過載的方法或者remove()過載的方法都是類似的。

總的來說就是arraylist內部維護了乙個動態的陣列,我們增刪改查都是對這個陣列進行操作。

transient

int size;

public

linkedlist()

這個無參構造很簡單。

public

void

add(int var1, e var2) else

}

第一步this.checkpositionindex(var1)很簡單,就是去檢查索引的合法性,不合法就丟擲索引越界異常

private

void

checkpositionindex(int var1)

}private

boolean

ispositionindex(int var1)

第二步,如果插入點是集合的末尾,進入linklast(e var1)

void linklast(e var1)  else 

++this.size;

++this.modcount;

}

這裡涉及到了linkedlist的靜態內部類node

private

static

class node

}

node表示鍊錶的結點item表示當前節點處的元素,next指向了下乙個結點,prev指向了上乙個結點。由此可見,linkedlist是基於雙向鍊錶的資料結構。

那麼我們再看linklast(e var1)就一目了然了,就是在鍊錶尾部增加了乙個新的結點罷了。

如果插入點不是在尾部,就進入linkbefore(e var1, linkedlist.node var2)

void linkbefore(e var1, linkedlist.node

var2) else

++this.size

; ++this.modcount

; }

做的操作也顯而易見,在鍊錶當中插入了乙個新的結點

至於其他add()remove()等等操作也是類似的。

總的來說就是linkedlist內部維護了乙個雙向鍊錶,我們增刪改查都是對這個鍊錶進行操作。

1.arraylist基於陣列,linkedlist基於鍊錶

2.對於隨機訪問get()set()arraylist優於linkedlist,因為linkedlist要移動指標

3.對於add()remove()linkedlist比較佔優勢,因為arraylist要移動資料

4.其他操作indexof(),lastindexof(),contains等(),兩者差不多。

以上只是理論上分析,事實上也不一定,比如arraylist在末尾插入和刪除資料就不涉及到資料移動。

而且實際業務場景可能很複雜,孰優孰劣需要綜合考慮。

參考:arraylist和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 而如果是在多執行緒情...