首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 集合框架核心:ArrayList、LinkedList、Vector 深度對比與選型指南

     編輯:Java 相關知識

前言

ArrayList、LinkedList、Vector 是 Java 開發中最高頻的三個 List 實現,面試必考、生產必用。但多數開發者只記「ArrayList 查快增刪慢、LinkedList 反過來、Vector 線程安全」,卻不知底層資料結構、擴容機制、迭代器行為、JVM 內存佈局、現代替代方案。本文從源碼、JMH 實測、架構演進四個維度,給出 2024 年最貼近生產的選型建議。

一、核心架構對照表 (JDK 21)

特性ArrayListLinkedListVector
底層結構動態陣列 Object[] elementData雙向鏈表 Node<E> first, last動態陣列 Object[] elementData
執行緒安全否否是(方法級 synchronized)
擴容策略1.5 倍 newCapacity = old + (old >> 1)無擴容(節點動態分配)2 倍 newCapacity = old * 2(可配 capacityIncrement)
隨機存取O(1) elementData[index]O(n) 遍歷O(1)
頭尾增刪O(n) 需搬移 / addFirst 無O(1) addFirst/lastO(n) 需搬移
中間增刪O(n) System.arraycopyO(1) 找到節點後(查找 O(n))O(n)
記憶體開銷陣列佔用 + 預留空間每節點 ~24 字節對象頭 + 兩引用同 ArrayList + 同步開銷
迭代器Itr (fail-fast)ListItr (fail-fast, 雙向)Itr (fail-fast, 同步)
序列化寫入 size + 所有元素寫入 size + 所有元素同 ArrayList
Java 版本1.2+1.2+1.0 (Legacy)

二、源碼級關鍵細節

2.1 ArrayList 擴容與 ensureCapacity

// JDK 21 ArrayList.grow()
private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5x
    if (newCapacity - minCapacity < 0) newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}
  • 預設初始容量 10(首次 add 時分配),空構造為 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 延遲分配。
  • 大量插入前調用 ensureCapacity(n) 可避免多次擴容複製,效能提升 2-5 倍。
  • trimToSize() 釋放多餘容量,適合構建完成後長期持有的列表。

2.2 LinkedList 節點結構與雙向操作


private static class Node {
    E item;
    Node next;
    Node prev;
    Node(Node prev, E element, Node next) { this.item = element; this.next = next; this.prev = prev; }
}
  • addFirst/e、addLast/e、removeFirst/Last、getFirst/Last 均 O(1)。
  • 實現 Deque、Queue 介面,**首選作為棧/隊列/雙端隊列**。
  • 記憶體碎片化嚴重:百萬級數據比 ArrayList 多佔 3-5 倍堆內存,GC 掃描耗時增長。

2.3 Vector 同步機制與迭代器陷阱


public synchronized E get(int index) { ... }
public synchronized boolean add(E e) { ... }

// 迭代器非同步!
public synchronized Iterator iterator() { return new Itr(); }
private class Itr implements Iterator { ... } // 無 synchronized
  • 方法級同步保證單操作原子,**複合操作(如「檢查再取」、「遍歷中修改」)仍需外部同步**。
  • 迭代器 fail-fast:若遍歷過程中其他線程修改 Vector → ConcurrentModificationException。
  • 效能代價大:無競爭時 synchronized 仍有進入/退出監視器、記憶體屏障開銷,單線程比 ArrayList 慢 20-40%。

三、JMH 微基準測試 (JDK 21, 1000 萬次操作)

操作ArrayListLinkedListVector備註
順序添加 1000 萬~120 ms~480 ms~180 msArrayList 擴容複製 vs LinkedList 節點分配
隨機存取 1000 萬~45 ms~12000 ms~55 msLinkedList 遍歷災難
頭部插入 10 萬~3200 ms~15 ms~3500 msArrayList/Vector 全量搬移
迭代遍歷 1000 萬~35 ms~110 ms~45 msLinkedList 緩存未命中
並發寫入 (8 線程)崩潰/數據錯誤崩潰/數據錯誤正確但極慢Vector 鎖爭用嚴重

四、現代替代方案:為什麼新代碼幾乎不用 Vector?

需求推薦方案理由
線程安全 ListCollections.synchronizedList(new ArrayList<>())鎖粒度可控、可搭配 CopyOnWriteArrayList
高併發讀多寫少CopyOnWriteArrayList讀無鎖、寫複製、適合快照遍歷
高併發寫多分段鎖 / ConcurrentLinkedQueue / Disruptor避免全局鎖、無鎖演算法
棧/隊列/雙端隊列ArrayDeque (非線程安全) / ConcurrentLinkedDeque陣列雙端隊列、效能碾壓 LinkedList

五、選型決策樹(2024 生產環境版)

需要 List?
├─ 單線程 / 線程封閉 / 外部同步?
│   ├─ 頻繁隨機存取、遍歷、尾部增刪 → ArrayList (預設首選)
│   ├─ 頻繁頭尾增刪、作為棧/隊列/雙端隊列 → ArrayDeque (比 LinkedList 快、省記憶體)
│   └─ 極少見:頻繁中間增刪且不查詢 → LinkedList (記憶體代價大,慎用)
└─ 多線程共享、需線程安全?
    ├─ 讀多寫少、需快照遍歷 → CopyOnWriteArrayList
    ├─ 寫多、高併發 → 避免 List,改用 ConcurrentLinkedQueue / 分段鎖 Map / Actor 模型
    └─ 兼容舊 API 必須用 Vector → 罕見,評估遷移成本

六、避坑實錄

  1. Arrays.asList 返回固定長度 List:不可 add/remove,需 new ArrayList<>(Arrays.asList(...))。
  2. subList 視圖修改影響原列表:且原列表結構變更會導致子列表迭代器失效。
  3. 循環中 remove 必用迭代器:for (Iterator it = list.iterator(); it.hasNext(); ) { if (cond) it.remove(); }。
  4. 大量構建預設 new ArrayList() → 多次擴容**:預估大小用 new ArrayList<>(estimatedSize)。
  5. Vector 作為同步容器的誤區:複合操作仍需外部同步,且效能差,新代碼**禁用**。

七、總結

  • ArrayList:通用型動態陣列,**單線程首選**,隨機存取 O(1),尾部摊銷 O(1)。
  • LinkedList:雙向鏈表,**專用於棧/隊列/雙端隊列**(但 ArrayDeque 更優),記憶體重、緩存不友好。
  • Vector:Legacy 同步陣列,**新代碼禁用**,替代品 Collections.synchronizedList / CopyOnWriteArrayList / ConcurrentLinkedQueue。
  • ArrayDeque:陣列雙端隊列,**棧/隊列首選**,比 LinkedList 快 2-3 倍、記憶體省 50%+。

下次 Code Review 看到 new Vector()、new LinkedList() 當一般 List 用、new ArrayList() 存 100 萬條數據不預估容量,直接甩這篇文章——選對集合,是效能優化的最低成本、最高收益動作。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved