1. 程式人生 > 實用技巧 >集合類

集合類

List

ArrayList底層是陣列,LinkedList底層是連結串列。陣列遍歷速度快,LinkedList增刪元素快。

在工作中一般就用ArrayList,而不用LinkedList,原因也很簡單:

  • 在工作中,遍歷的需求比增刪多,即便是增加元素往往也只是從尾部插入元素,而ArrayList在尾部插入元素也是O(1)

  • ArrayList增刪沒有想象中慢,ArrayList的增刪底層呼叫的copyOf()被優化過,加上現代CPU對記憶體可以塊操作,普通大小的ArrayList增刪比LinkedList更快。

List集合常用的子類有三個:

  • ArrayList,底層資料結構是陣列。執行緒不安全

    • ArrayList是基於動態陣列實現的,在增刪時候,需要陣列的拷貝複製

    • ArrayList的預設初始化容量是10,每次擴容時候增加原先容量的一半,也就是變為原來的1.5倍

    • 刪除元素時不會減少容量,若希望減少容量則呼叫trimToSize()

    • 它不是執行緒安全的。它能存放null值。

  • LinkedList,底層資料結構是連結串列。執行緒不安全

    • 底層實現是雙向連結串列[雙向連結串列方便實現往前遍歷]

  • Vector,底層資料結構是陣列。執行緒安全,方法帶有synchronized

    • 底層是陣列,現在已少用,被ArrayList替代,原因有兩個:

    • Vector所有方法都是同步,有效能損失

    • Vector初始length是10 超過length時 以100%比率增長,相比於ArrayList更多消耗記憶體

Set

Set常用子類:

  • HashSet集合,底層資料結構是雜湊表(是一個元素為連結串列的陣列)

  • TreeSet集合,底層資料結構是紅黑樹(是一個自平衡的二叉樹),保證元素的排序方式

  • LinkedHashSet集合,底層資料結構由雜湊表和連結串列組成。

Map

散列表

散列表為每個物件計算出一個整數,稱為雜湊碼根據這些計算出來的整數(雜湊碼)儲存在對應的位置上!在Java中,散列表用的是連結串列陣列實現的,每個列表稱之為桶

一個桶上可能會遇到被佔用的情況(hashCode雜湊碼相同,就儲存在同一個位置上)

,這種情況是無法避免的,這種現象稱之為:雜湊衝突

  • 此時需要用該物件與桶上的物件進行比較,看看該物件是否存在桶子上了~如果存在,就不添加了,如果不存在則新增到桶子上

  • 當然了,如果hashcode函式設計得足夠好,桶的數目也足夠,這種比較是很少的~

  • JDK1.8中,桶滿時會從連結串列變成平衡二叉樹

各種常見的樹的用途:

紅黑樹

紅黑樹用的是也是兩種方式來替代2-3樹不斷的節點交換操作:

  • 旋轉:順時針旋轉和逆時針旋轉

  • 反色:交換紅黑的顏色

  • 這個兩個實現比2-3樹交換的節點(合併,分解)要方便一些

紅黑樹為了保持平衡,還有制定一些約束,遵守這些約束的才能叫做紅黑樹:

  1. 紅黑樹是二叉搜尋樹。

  2. 根節點是黑色

  3. 每個葉子節點都是黑色的空節點(NIL節點)

  4. 每個紅色節點的兩個子節點都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)

  5. 從任一節點到其每個葉子的所有路徑都包含相同數目的黑色節點(每一條樹鏈上的黑色節點數量(稱之為“黑高”)必須相等)

HashMap和HashTable

從儲存結構和實現來講基本上都是相同的。它和HashMap的最大的不同是它是執行緒安全的,另外它不允許key和value為null。Hashtable是個過時的集合類,不建議在新程式碼中使用,不需要執行緒安全的場合可以用HashMap替換,需要執行緒安全的場合可以用ConcurrentHashMap替換

Queue佇列

不知道大家有沒有學過生產者和消費者模式,秋招面試的時候可能會讓你手寫一段這樣的程式碼。最簡單的方式就是用阻塞佇列去寫