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 而如果是在多執行緒情...