核心差異速覽
| 特性 | ArrayList | Vector |
| 線程安全 | 非線程安全 | 所有方法 synchronized,線程安全 |
| 擴容倍數 | 1.5 倍 + 1(newCapacity = old*3/2+1) | 2 倍(或指定 capacityIncrement) |
| 性能 | 高(無鎖開銷) | 低(同步鎖開銷大) |
| 遍歷速度 | 快(RandomAccess + 連續內存) | 同 ArrayList |
| 插入/刪除中間 | 慢(需數組複製移動) | 同 ArrayList |
| 推薦場景 | 單線程、高頻隨機訪問、作為首選 List 實現 | 極少見,僅維護舊代碼或極簡單多線程場景 |
源碼級擴容機制分析
ArrayList (JDK 17)
public boolean add(E e) {
ensureCapacityInternal(size + 1);
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;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5倍
if (newCapacity - minCapacity < 0) newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
Vector (JDK 17)
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
private void ensureCapacityHelper(int minCapacity) {
if (minCapacity - elementData.length > 0) {
int oldCapacity = elementData.length;
int newCapacity = (capacityIncrement > 0) ?
oldCapacity + capacityIncrement : oldCapacity * 2; // 默認 2倍
if (newCapacity - minCapacity < 0) newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
為什麼不推薦 Vector?
- 鎖粒度過粗:每個方法加鎖,即使單線程也承擔進入/退出監視器開銷。
- 替代方案更優:多線程環境首選
Collections.synchronizedList(new ArrayList<>()) 或並發包 CopyOnWriteArrayList(讀多寫少) / ConcurrentLinkedQueue(隊列語義)。
- 擴容策略固定 2 倍,記憶體浪費可能大於 ArrayList 的 1.5 倍。
LinkedList 補充對比
- 底層雙向鏈表,首尾增刪 O(1),適合棧/隊列/雙端隊列。
- 隨機訪問 O(n),不實現 RandomAccess,遍歷建議用迭代器或 for-each。
- 記憶體佔用大(每節點額外 2 引用 + 對象頭)。
選型決策樹
需要線程安全?
├─ 是 → 讀多寫少 → CopyOnWriteArrayList
│ 寫多或需併發隊列 → ConcurrentLinkedQueue / 並發包其他結構
└─ 否 → 需頻繁中間增刪 → LinkedList
預設首選 → ArrayList