1. 程式人生 > >ArrayList和LinkedList的區別與聯絡

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));
    }
}

就不上執行截圖了,因為等了很久也沒有出結果。讀者可以複製程式碼執行下看看