ArrayList 和 LinkedList 的區別(面試常考)

最近秋招面試時經常碰到這道題,雖然自己也答出來了,但總感覺不是那麼完善,特此總結一下。

ArrayList 和 LinkedList 都實現了 List 接口。

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
        
public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
    

我們可以看到 LinkedList 還實現了 Deque 這個隊列接口,可以作爲雙向隊列的實現。

ArrayList 的底層是動態數組,可以實現動態擴容,每次擴容成原來的 1.5 倍,相對於原來的基本數組,它封裝了數組插入、刪除、擴容這些數組操作的細節。
另外,它支持隨機訪問,但是刪除或者插入元素效率很低,例如在數組中間插入一個元素,必須把這個元素以後的元素全部向後搬移一個位置。

LinkedList 訪問一個元素時一般是通過 for 循環獲取到這個元素所在位置,然後返回這個元素,時間複雜度爲 O(n)。刪除或者插入一個給定指針指向的結點時間複雜度爲 O(1)。

我們下面寫個程序來模擬兩種數據結構的隨機查找過程。

/**
 * ArrayList 底層是動態數組,利用數組下標隨機訪問元素很高效。
 */
public class ArrayList {
    public static void main(String[] args) {
        List<Integer> arrayList = new java.util.ArrayList<>();
        List<Integer> linkedList = new LinkedList<>();
        for(int i = 0; i< 100000; i++) {
            arrayList.add(i);
            linkedList.add(i);
        }

        long arraylisttime = getTime(arrayList);
        System.out.println(arraylisttime + " ms");
        long linkedListTime = getTime(linkedList);
        System.out.println(linkedListTime + " ms");
      
    }

    private static long getTime(List<Integer> list) {
        long curTime =  System.currentTimeMillis();
        for(int i = 0; i< list.size(); i++) {
            // ArrayList 通過下標訪問元素。
            list.get(i);
        }
        long wasteTime = System.currentTimeMillis();
        return wasteTime - curTime;
    }
}

/** 結果:
* 8 ms
* 7892 ms
*/

可以看出數組隨機訪問的性能確實非常高,特別是在數據量大的時候。

原理就是數組在內存中佔用連續的存儲空間並且存儲相同的元素。所以根據下標訪問某一個元素時可以直接計算得到元素所在位置,大大加快了訪問速度。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章