public interface RandomAccess {} // 標記接口,無任何方法
JDK 文檔:「標記接口,表明 List 實現支援快速(通常為常數時間)隨機訪問。讓通用演算法根據訪問模式調整行為以獲得更好效能。」
| List 實現 | 實現 RandomAccess | 底層結構 | 隨機訪問 | 順序訪問 |
|---|---|---|---|---|
ArrayList | ✅ 是 | 動態陣列 | O(1) 極快 | 快 |
Vector | ✅ 是 | 動態陣列(同步) | O(1) | 快 |
LinkedList | ❌ 否 | 雙向鏈表 | O(n) 慢 | 快 |
CopyOnWriteArrayList | ✅ 是 | 陣列快照 | O(1) | 快 |
AttributeList | ✅ 是 | 陣列 | O(1) | 快 |
@Test
public void benchmark() {
List arrayList = new ArrayList<>();
List linkedList = new LinkedList<>();
init(arrayList, 1000);
init(linkedList, 1000);
// 隨機訪問模式:for 循環 + get(i)
long t1 = time(() -> randomAccess(arrayList)); // ~10 ms
long t2 = time(() -> randomAccess(linkedList)); // ~434 ms (慢 43 倍!)
// 順序訪問模式:Iterator
long t3 = time(() -> sequentialAccess(arrayList)); // ~39 ms
long t4 = time(() -> sequentialAccess(linkedList)); // ~27 ms (略快)
}
public static void traverseOptimized(List list, Consumer action) {
if (list instanceof RandomAccess) {
// 隨機訪問優勢:for 循環
for (int i = 0, n = list.size(); i < n; i++) {
action.accept(list.get(i));
}
} else {
// 順序訪問優勢:Iterator
for (T item : list) { // 隱式 Iterator
action.accept(item);
}
}
}
某些實現(如樹結構列表)隨機訪問為 O(log n),介於常數與線性之間。JDK 建議:「若列表很大時提供漸進線性訪問,但實際上是常數時間,通常應實現此接口。」
instanceof RandomAccess 判斷list.stream() 內部用 Spliterator,自動適配,無需手動優化RandomAccess 是標記接口界的「教科書級設計」:零方法、語義明確、讓演算法根據數據結構特性自適應。記住口訣:陣列基 → 實現它,鏈表基 → 別實現,遍歷時 → 檢測它。