ArrayList和LinkedList的區別與聯絡
ArrayList和Vector使用了陣列去實現。
LinkedList使用了連結串列資料結構
這是兩種不同的技術,所以使用它們的時候是有區別的。
1)首先我們來看看增加到List結尾的場景。如果ArrayList的容量在初始化的時候,設定的足夠大。那麼此時ArrayList的效能是非常好的。但是如果ArrayList的容量是10的話,那麼超出了現有的陣列的長度是要進行自動擴容的。擴容的公式是 (oldLength * 3 ) / 2 + 1
這就要涉及到大量的陣列的複製操作
我們在來看一看LinkedList由於它是連結串列結構的,所以不需要維護容量的大小,從這點說,他比ArrayList有一定的優勢。然而,每次的元素增加都需要新建一個Entry物件,並進行更多的賦值操作。在頻繁的系統呼叫中,對效能會產生一定的影響
下面我們來寫個程式測試一下。
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListTest {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
long arrayListStartTime = System.currentTimeMillis();
for(int i = 0 ; i < 10000 ; i++) {
arrayList.add("a" + i);
}
System.out.println("ArrayList在尾部增加元素消耗了" + (System.currentTimeMillis() - arrayListStartTime));
LinkedList<String> linkedList = new LinkedList<>();
long linkedListStartTime = System.currentTimeMillis();
for (int i = 0 ; i < 10000 ; i++) {
linkedList.add("a" + i);
}
System.out.println("LinkedList在尾部增加元素消耗了" + (System.currentTimeMillis() - linkedListStartTime));
}
}
2)增加元素到列表任意位置
當增加元素到連結串列任意位置的時候,LinkedList的優勢就體現出來了。因為ArrayList是陣列實現的。所以肯定要移動陣列元素,而且插入的位置越靠前,效能影響越大。由於LinkedList是連結串列實現的。所以只需要改變指標指向就可以了。
我們來寫個程式來測試下
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListTest {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
long arrayListStartTime = System.currentTimeMillis();
for(int i = 0 ; i < 1000000 ; i++) {
arrayList.add("a" + i);
}
System.out.println("ArrayList在尾部增加元素消耗了" + (System.currentTimeMillis() - arrayListStartTime));
LinkedList<String> linkedList = new LinkedList<>();
long linkedListStartTime = System.currentTimeMillis();
for(int i = 0 ; i < 1000000 ; i++) {
linkedList.add("a" + i);
}
System.out.println("LinkedList在尾部增加元素消耗了" + (System.currentTimeMillis() - linkedListStartTime));
System.out.println("=====================================");
long addElementInArrayListAnyWhereBegin = System.currentTimeMillis();
for(int i = 0 ; i < 10000 ; i++) {
arrayList.add(i, "aaa");
}
System.out.println("ArrayList在任意位置插入元素消耗了" + (System.currentTimeMillis() - addElementInArrayListAnyWhereBegin));
long addElementInLinkedListAnyWhereBegin = System.currentTimeMillis();
for(int i = 0 ; i < 10000 ; i++) {
linkedList.add(i, "aaa");
}
System.out.println("LinkedList在任意位置插入元素消耗了" + (System.currentTimeMillis() - addElementInLinkedListAnyWhereBegin));
}
}
3)刪除任意位置元素
這個跟任意位置插入有點像。
在刪除掉後ArrayList是要進行移動的。
並且刪除的位置越靠前,開銷越大。
4)容量引數
ArrayList是要維護一個容量大小的。如果我們知道我們大概要存放多少的元素。我們應該在ArrayList的構造方法中宣告出來。從而減少陣列的擴容次數。效能自然就上來了。
5)遍歷操作
當我們在遍歷的時候,
先上一張圖吧
我們也來寫個程式測一下
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListTest {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
long arrayListStartTime = System.currentTimeMillis();
for(int i = 0 ; i < 1000000 ; i++) {
arrayList.add("a" + i);
}
System.out.println("ArrayList在尾部增加元素消耗了" + (System.currentTimeMillis() - arrayListStartTime));
LinkedList<String> linkedList = new LinkedList<>();
long linkedListStartTime = System.currentTimeMillis();
for(int i = 0 ; i < 1000000 ; i++) {
linkedList.add("a" + i);
}
System.out.println("LinkedList在尾部增加元素消耗了" + (System.currentTimeMillis() - linkedListStartTime));
System.out.println("=====================================");
long addElementInArrayListAnyWhereBegin = System.currentTimeMillis();
for(int i = 0 ; i < 10000 ; i++) {
arrayList.add(i, "aaa");
}
System.out.println("ArrayList在任意位置插入元素消耗了" + (System.currentTimeMillis() - addElementInArrayListAnyWhereBegin));
long addElementInLinkedListAnyWhereBegin = System.currentTimeMillis();
for(int i = 0 ; i < 10000 ; i++) {
linkedList.add(i, "aaa");
}
System.out.println("LinkedList在任意位置插入元素消耗了" + (System.currentTimeMillis() - addElementInLinkedListAnyWhereBegin));
System.out.println("=================================");
StringBuffer stringBuffer = new StringBuffer();
long getAllArrayListBegin = System.currentTimeMillis();
for(int i = 0 ; i < arrayList.size(); i++) {
stringBuffer.append(arrayList.get(i));
}
System.out.println("遍歷ArrayList消耗了" + (System.currentTimeMillis() - getAllArrayListBegin));
long getAllLinkedListBegin = System.currentTimeMillis();
for(int i = 0 ; i < linkedList.size(); i++) {
stringBuffer.append(linkedList.get(i));
}
System.out.println("遍歷LinkedList消耗了" + (System.currentTimeMillis() - getAllLinkedListBegin));
}
}
就不上執行截圖了,因為等了很久也沒有出結果。讀者可以複製程式碼執行下看看