源碼淺析 ArrayList、Vector、LinkedList 的區(qū)別

從類的定義淺析

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
public class Vector<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

public abstract class AbstractSequentialList<E> extends AbstractList<E> {
首先從繼承父類來(lái)看:

ArrayList & Vector 都繼承了AbstractList 抽象類(提供了
List 接口的默認(rèn)實(shí)現(xiàn),支持隨機(jī)訪問(wèn));
LinkedList 繼承了 AbstractSequentialList(提供了
List 接口的簡(jiǎn)化實(shí)現(xiàn),簡(jiǎn)化在只支持按次序訪問(wèn));

其次從實(shí)現(xiàn)接口來(lái)看:

①、三者都實(shí)現(xiàn)了 List 接口(定義了列表必須實(shí)現(xiàn)的方法)、Cloneable 接口(可以調(diào)用Object.clone方法返回該對(duì)象的淺拷貝)、java.io.Serializable 接口(支持序列化和反序列化);
②、ArrayList & Vector 兩者都實(shí)現(xiàn)了 RandomAccess 接口(提供了快速隨機(jī)訪問(wèn)存儲(chǔ)的元素的功能),而 LinkedList 實(shí)現(xiàn)了 Deque 接口(支持雙向隊(duì)列

從類的屬性淺析

ArrayList.java

    private static final int DEFAULT_CAPACITY = 10; // 默認(rèn)容量
    transient Object[] elementData;                 // 裝元素的容器,不可序列化
    private int size;                               // ArrayList 的大小

Vector.java

    protected Object[] elementData;   // 裝元素的容器
    protected int elementCount;       // Vector 的大小
    protected int capacityIncrement;  // 每次 Vector 容量增加時(shí)的增量值

LinkedList.java

    transient int size = 0;     // LinkedList 的大小
    transient Node<E> first;    // 頭指針
    transient Node<E> last;     // 尾指針
    // 結(jié)點(diǎn)的定義
    private static class Node<E> {
        E item;       // 結(jié)點(diǎn)值
        Node<E> next; // 下一個(gè)結(jié)點(diǎn)
        Node<E> prev; // 前一個(gè)結(jié)點(diǎn)
        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

由上源碼可知:
①、ArrayList & Vector 兩者底層的數(shù)據(jù)結(jié)構(gòu)是數(shù)組結(jié)構(gòu),所以改查很快,增刪較慢(又因?yàn)?Vector線程同步的,所以增刪改查都比 ArrayList 慢)。而 LinkedList 的底層的數(shù)據(jù)結(jié)構(gòu)是鏈表結(jié)構(gòu),所以改查較慢,增刪較快
②、ArrayList & Vector 底層都維護(hù)了一個(gè) Object[] 對(duì)象數(shù)組用于存儲(chǔ)對(duì)象,默認(rèn)數(shù)組的長(zhǎng)度是 10。但是 ArrayList 的對(duì)象數(shù)組,通過(guò) transient 修飾,不可序列化。
③、Vector 維護(hù)了一個(gè) capacityIncrement 字段,可以通過(guò)構(gòu)造器去設(shè)置每次擴(kuò)容的大小,而 ArrayList 沒(méi)有。

從類的擴(kuò)容方法淺析

ArrayList.java

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 擴(kuò)容
        elementData[size++] = e;
        return true;
    }
    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        ensureExplicitCapacity(minCapacity);
    }
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    private void grow(int minCapacity) {
        int oldCapacity = elementData.length;
        // 數(shù)組擴(kuò)容:增大 0.5 倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

Vector.java

    public synchronized boolean add(E e) {
        modCount++;
        // 擴(kuò)容方法
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }
    private void ensureCapacityHelper(int minCapacity) {
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    private void grow(int minCapacity) {
        int oldCapacity = elementData.length;
        // 數(shù)組擴(kuò)容:增大 1 倍(capacityIncrement  表示每次 Vector 容量增加時(shí)的增量值)
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

由上源碼可知:
ArrayList 擴(kuò)容時(shí),容量自動(dòng)增長(zhǎng)為原來(lái)的容量的 1.5 倍,而 Vector 的容量自動(dòng)增長(zhǎng)為原來(lái)的容量的 2 倍。

從遍歷的方法淺析

三者都支持三種遍歷方式:for-each()(幾乎與迭代器一樣)、迭代器方式、下標(biāo)遞增或遞減循環(huán)
ArrayList,下標(biāo)遞增或遞減循環(huán)方式是速度最快的,但是 for-each() 實(shí)現(xiàn)更加簡(jiǎn)單,且速度沒(méi)慢太多,推薦使用。
LinkedList,for-each() 方式是速度最快的。

總結(jié)

①、
ArrayList & Vector 支持隨機(jī)訪問(wèn);
LinkedList 只支持按次序訪問(wèn);

②、
三者都定義了列表必須實(shí)現(xiàn)的方法、可以調(diào)用Object.clone方法返回該對(duì)象的淺拷貝、支持序列化和反序列化;

③、
ArrayList & Vector 提供了隨機(jī)訪問(wèn)功能;
LinkedList 支持雙向隊(duì)列;

④、
ArrayList & Vector數(shù)組結(jié)構(gòu),所以改查很快,增刪較慢(又因?yàn)?Vector線程同步的,所以增刪改查都比 ArrayList 慢)。
LinkedList鏈表結(jié)構(gòu),所以改查較慢,增刪較快。

⑤、
ArrayList & Vector 底層都維護(hù)了一個(gè) Object[] 對(duì)象數(shù)組用于存儲(chǔ)對(duì)象,默認(rèn)數(shù)組的長(zhǎng)度是 10。
但是 ArrayList 的對(duì)象數(shù)組,通過(guò) transient 修飾,不可序列化

⑥、
Vector 維護(hù)了一個(gè) capacityIncrement 字段,可以通過(guò)構(gòu)造器去設(shè)置每次擴(kuò)容的大小,而 ArrayList 沒(méi)有。

⑦、
ArrayList 擴(kuò)容時(shí),容量自動(dòng)增長(zhǎng)為原來(lái)的容量的 1.5 倍;
Vector 擴(kuò)容時(shí),容量自動(dòng)增長(zhǎng)為原來(lái)的容量的 2 倍。

⑧、
無(wú)論哪種,都推薦使用 for-each() 遍歷的方式。

注意:Vector 屬于遺留容器,已經(jīng)不推薦使用。

Q:但 ArrayList 和 LinkedListed 都是非線程安全的,所以如果遇到多個(gè)線程操作同一個(gè)容器的場(chǎng)景,該怎么處理?
A:可以通過(guò)工具類 Collections 中的 synchronizedList() 方法將其轉(zhuǎn)換成線程安全的容器后再使用(這是對(duì)裝潢模式的應(yīng)用,將已有對(duì)象傳入另一個(gè)類的構(gòu)造器中創(chuàng)建新的對(duì)象來(lái)增強(qiáng)實(shí)現(xiàn))。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容