這是 Java 面試高頻題,也是日常開發選型的關鍵。本文從線程安全、擴容機制、歷史淵源、性能特點四個維度深度對比,並給出現代開發選型建議。
| 維度 | ArrayList | Vector |
|---|---|---|
| 線程安全 | 非線程安全 | 線程安全(方法級 synchronized) |
| 擴容倍數 | 1.5 倍 | 2 倍(默認雙倍) |
| 性能 | 高(無鎖開銷) | 低(同步開銷) |
| 推出版本 | JDK 1.2 | JDK 1.0(古老集合) |
| 繼承體系 | List → AbstractList | List → AbstractList |
// ArrayList (JDK 17)
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5 倍
elementData = Arrays.copyOf(elementData, newCapacity);
}
// Vector
public synchronized void ensureCapacityHelper(int minCapacity) {
if (minCapacity > elementData.length) {
int newCapacity = (capacityIncrement > 0) ?
elementData.length + capacityIncrement :
elementData.length * 2; // 默認 2 倍
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
Collections.synchronizedList(new ArrayList<>()):鎖粒度同 VectorCopyOnWriteArrayList:讀多寫少、遍歷不加鎖、弱一致性List<T> list = new ArrayList<>(); + 手動 synchronized/ReentrantLock:精細控制鎖範圍| 維度 | HashMap | Hashtable |
|---|---|---|
| 線程安全 | 非線程安全 | 線程安全(方法級 synchronized) |
| Null 鍵/值 | 允許 1 個 null key、多個 null value | 不允許 null key/value(拋 NPE) |
| 初始容量 | 16(默認) | 11(默認) |
| 擴容方式 | 2 的冪次(2倍) | 2n+1(約 2 倍+1) |
| 哈希計算 | 擾動函數 + (n-1)&hash | 直接 key.hashCode() |
| 繼承體系 | Map → AbstractMap | Map → Dictionary(舊) |
| 推出版本 | JDK 1.2 | JDK 1.0 |
// HashMap putVal 允許 null key
if (key == null) {
return putForNullKey(value); // 存放在 table[0]
}
// Hashtable put 直接拋異常
if (value == null) {
throw new NullPointerException();
}
ConcurrentHashMap(首選):JDK 8 采用 CAS + synchronized(節點級),分段鎖 → 節點鎖,高併發性能極佳Collections.synchronizedMap(new HashMap<>()):全鎖,性能同 HashtableLinkedHashMapTreeMapWeakHashMapEnumMap(極致性能)
Collection
├── List
│ ├── ArrayList
│ ├── LinkedList
│ ├── Vector
│ │ └── Stack
│ └── CopyOnWriteArrayList
└── Set
├── HashSet
├── LinkedHashSet
├── TreeSet
└── CopyOnWriteArraySet
Map
├── HashMap
├── LinkedHashMap
├── TreeMap
├── WeakHashMap
├── IdentityHashMap
├── EnumMap
├── Hashtable
│ └── Properties
└── ConcurrentHashMap
└── ConcurrentSkipListMap
需要 List?
├── 單線程/外部同步 → ArrayList
├── 多線程、讀多寫少 → CopyOnWriteArrayList
├── 多線程、寫多、需強一致性 → ArrayList + 手動鎖 / Collections.synchronizedList
└── 作為棧/隊列 → ArrayDeque (首選) / LinkedList
需要 Map?
├── 單線程 → HashMap
├── 多線程 → ConcurrentHashMap
├── 需保持插入順序 → LinkedHashMap
├── 需按鍵排序 → TreeMap
├── 鍵為枚舉 → EnumMap
└── 鍵需弱引用 → WeakHashMap
現代 Java 開發原則: