6.對比Vector、ArrayList、LinkedList有何區別以及常見的集合問題
阿新 • • 發佈:2018-12-25
第6講:對比Vector、ArrayList、LinkedList有何區別
典型回答:
相同點:
- 三者都是實現集合框架中的List,也就是所謂的有序集合,存取有序,有索引,可以重複,具體功能比較相似,都能實現增刪改查,都提供迭代器以遍歷其內容。
區別:
- Vector是Java早期提供的執行緒安全的動態陣列,執行緒安全,增刪改查都比較慢。
- ArrayList底層是陣列,執行緒不安全,查詢和修改快,增刪慢,使用get和set方法是花費常數時間的,但是如果插入元素和刪除元素,除非插入和刪除的位置都在表末尾,否則程式碼開銷會很大,因為裡面需要陣列的移動。與Vector類似,也是可以根據需要調整容量,不過二者的調整邏輯有所區別,Vector在擴容時提高1倍,而ArrayList則是增加50%
- LinkedList是雙向連結串列實現的,執行緒不安全,所以get會非常消耗資源,除非位置離頭部很近,但是插入和刪除元素花費常數時間。
擴充套件知識
1.集合框架
- List,有序集合,可重複,增刪改查
- Set,無序不可重複
- Queue/Deque,除了集合的功能,還支援類似的先入先出(FIFO)或者後入先出(LIFO)
2.Map和Set
- TreeSet實際上是利用TreeMap實現的,Java類庫建立了一個Dummy物件”PRESENT”作為value,然後所有插入的物件是以鍵的形式放入了TreeMap裡面。
- 同理,HashSet也是以HashMap為基礎實現的。
3.Set的一些使用說明
- TreeSet支援自然順序訪問,但是新增、刪除、包含等操作相對要低效(log(n)時間)
- HashSet則是利用Hash演算法,理想情況下,如果雜湊雜湊正常,可以提供常數時間的新增、刪除、包含等操作,但是不保證有序
- LinkedhashSet,內部構建了一個記錄插入順序的雙向連結串列,因此提供了按照插入順序遍歷的能力,於此同時,也保證了常數時間的新增、刪除、包含等操作,這些效能略低於HashSet,因為需要維護這些連結串列的開銷。
- 在遍歷列表時,HashSet效能受自身容量的影響,所以初始化時,除非有必要,不然不要將其背後的HashSet容量設定過大,而對於LinkedHashSet,由於其內部連結串列提供的方便,遍歷效能只和元素的多少有關。
4.Collections的synchronized方法
- Collections工具類中,提供了一系列的synchronized方法,比如:
List<T> synchronizedList(List<T> list)
,所以可以用類似的方法來實現基本的執行緒安全集合:List list =Collections.synchronizedList(new ArrayList());
其實現就是將每個方法,比如get\set\add之類,都通過synchronized新增同步支援,簡單粗暴,但是也非常實用。這些方法建立的執行緒安全集合,都符合迭代是fail-fast行為,當發生意外的併發修改時,儘早丟擲ConcurrentModificationException
異常,以避免不可預期的行為
5.排序
- 對於原始資料型別,目前使用的是所謂雙軸快速排序,是一種改進的快速排序演算法,早期版本是相對傳統的快速排序
- 對於物件資料型別,目前則是使用TimSort,思想上也是一種歸併和二分插入排序(binarySort)結合的優化排序演算法。TimSort 並不是 Java 的獨創,簡單說它的思路是查詢資料集中已經排好序的分割槽(這裡叫 run),然後合併這些分割槽來達到排序的目的。
6.思考題
先思考一個應用場景,比如你需要實現一個雲端計算任務排程系統,希望可以保證 VIP 客戶的任務被優先處理,你可以利用哪些資料結構或者標準的集合型別呢?更進一步講,類似場景大多是基於什麼資料結構呢?
- 自然就會想到優先順序隊列了,但還需要額外考慮vip再分級,即同等級vip的平權的問題,所以應該考慮除了直接的和vip等級相關的優先順序佇列優先順序規則問題,還得考慮同等級多個客戶互相不被單一客戶大量任務阻塞的問題。
- 其實我覺得應該參考銀行視窗,同時三個視窗,就是三個佇列,銀臺就是消費者執行緒,某一個視窗vip優先,沒有vip時也為普通客戶服務。要實現,要麼有個dispatcher,要麼保持vip通道不許普通進入,vip櫃檯閒時從其他佇列分配過來普通客戶