1. List概覽 html
List,就像它的名字暗示的同樣,是一組排列有序的元素。當咱們討論List的時候,很容易將它和Set做比較。Set是一組惟一的並且排列無序的元素。 java
下圖是集合類的層次結構圖。你能夠整體上知道咱們今天討論的主題。 程序員
從上圖可知,它們都實現了List接口。它們的用法差很少,主要的區別在於它們對於不一樣操做的操做速度不一樣。 數組
ArrayList是能夠改變大小的數組。當有元素添加到ArrayList中去時,它的大小動態的增長。元素能夠直接經過get()和set()方法進行訪問,由於ArrayList其實是數組。LinkedList是個雙向鏈表。它的add()和remove()方法比ArrayList快,可是get()和set()方法卻比ArrayList慢。Vector和ArrayList相似,可是Vector是同步的。若是在線程安全的環境下,使用ArrayList是更好的選擇。添加元素的時候,當超過初始容量的時候,Vector和ArrayList須要更多的空間:Vector須要將數組的大小增長一倍,而ArrayList須要增長50%。 安全
LinkedList還實現了Queue接口,這樣就比ArrayList和Vector多出了一些方法如offer(), peek(), poll()等。 性能
注意:ArrayList的初始容量(initial capacity)很小。咱們應該設置一個比較大的初始容量,這樣能夠避免從新改變大小。 測試
1
2
3
4
5
6
7
8
9
10
11
12
13
|
ArrayList al =newArrayList();
al.add(3);
al.add(2);
al.add(1);
al.add(4);
al.add(5);
al.add(6);
al.add(6);
Iterator iter1 = al.iterator();
while(iter1.hasNext()){
System.out.println(iter1.next());
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
LinkedList ll =newLinkedList();
ll.add(3);
ll.add(2);
ll.add(1);
ll.add(4);
ll.add(5);
ll.add(6);
ll.add(6);
Iterator iter2 = ll.iterator();
while(iter2.hasNext()){
System.out.println(iter2.next());
}
|
由上可見,它們的用法相同,主要的區別在於它們內部的實現,以及操做的複雜度的不一樣。 spa
Vector幾乎和ArrayList相等,主要的區別在於Vector是同步的。正由於此,Vector比ArrayList的開銷更大。一般大部分程序員都使用ArrayList,他們能夠本身寫代碼進行同步。 線程
時間複雜度以下: htm
* 表中的add()指的是add(E e)(便是在列表末尾添加元素),remove()方法指的是remove(int index)。
ArrayList對於任意索引的插入/刪除操做的時間複雜度是O(n),而在列表的尾部的操做時間爲O(1)。
LinkedList對於任意索引的插入/刪除操做的時間複雜度是O(n),而在列表的頭部或尾部的操做時間爲O(1)。
(譯者注:這裏原文解釋的不是太清楚。對於任意索引的插入/刪除操做
Arrays:
Linked Lists:
)
我使用下面的代碼測試它們的性能:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
ArrayList arrayList =newArrayList();
LinkedList linkedList =newLinkedList();
// ArrayList add
longstartTime = System.nanoTime();
for(inti =0; i <100000; i++) {
arrayList.add(i);
}
longendTime = System.nanoTime();
longduration = endTime - startTime;
System.out.println("ArrayList add: "+ duration);
// LinkedList add
startTime = System.nanoTime();
for(inti =0; i <100000; i++) {
linkedList.add(i);
}
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("LinkedList add: "+ duration);
// ArrayList get
startTime = System.nanoTime();
for(inti =0; i <10000; i++) {
arrayList.get(i);
}
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("ArrayList get: "+ duration);
// LinkedList get
startTime = System.nanoTime();
for(inti =0; i <10000; i++) { linkedList.get(i); } endTime = System.nanoTime(); duration = endTime - startTime; System.out.println("LinkedList get: "+ duration); // ArrayList remove startTime = System.nanoTime(); for (int i = 9999; i >=0; i--) {
arrayList.remove(i);
}
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("ArrayList remove: "+ duration);
// LinkedList remove
startTime = System.nanoTime();
for(inti =9999; i >=0; i--) {
linkedList.remove(i);
}
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("LinkedList remove: "+ duration);
|
輸出以下:
1
2
3
4
5
6
|
ArrayList add: 13265642
LinkedList add: 9550057
ArrayList get: 1543352
LinkedList get: 85085551
ArrayList remove: 199961301
LinkedList remove: 85768810
|
它們的性能的差異很顯著。LinkedList對於add()和remove()相對於ArrayList要快,可是get()要慢些。按照複雜度以及測試結果來看,咱們很容易知道何時該使用ArrayList,何時該使用LinkedList。簡而言之,下面的狀況該使用LinkedList: