List,Set,Queue,Map介面

nadooo發表於2024-08-06

List,Set,Queue,Map介面

一.List介面

List 介面是 Java 集合框架中的一個重要介面,它繼承自 Collection 介面。List 介面表示一個有序的集合,其中的元素可以重複。這意味著在 List 中,每個元素都有一個特定的索引位置,我們可以透過這個索引來訪問或操作元素。

List 介面的主要特點包括:

  1. 有序性List 集合中的元素是按照它們被插入的順序來儲存的。可以透過索引來訪問集合中的元素。
  2. 允許重複元素:與 Set 介面不同,List 允許儲存重複的元素。
  3. 提供額外的方法:除了從 Collection 介面繼承的方法外,List 介面還定義了一些用於插入、刪除和訪問列表元素的方法,比如 get(int index)add(int index, E element)remove(int index) 等。

List 介面的實現類主要包括:

  • ArrayList:基於動態陣列的資料結構實現的列表。它允許快速的隨機訪問,但在列表的末尾之外的位置插入或刪除元素時可能較慢,因為可能需要移動元素。
  • LinkedList:基於連結串列的資料結構實現的列表。它在列表的開頭和結尾進行插入和刪除操作非常快速,但在隨機訪問方面不如 ArrayList
  • Vector:是一個古老的 List 實現,它是同步的,但通常不推薦使用,因為效能較低,並且大多數需要同步的情況都可以透過使用 Collections.synchronizedList 方法將任何 List 包裝成同步的列表來更靈活地處理。
  • Stack:是 Vector 的一個子類,實現了後進先出(LIFO)的堆疊。不過,Stack 類被認為是過時的,Java 提供了 Deque 介面(及其實現類如 ArrayDeque)作為更現代的替代方案,以提供更強大的雙端佇列功能,同時也支援堆疊操作。

以下是一些 List 介面的常用方法:

  • boolean add(E e):向列表的末尾新增指定的元素。
  • void add(int index, E element):在列表的指定位置插入指定的元素。
  • E get(int index):返回列表中指定位置的元素。
  • E remove(int index):移除列表中指定位置的元素,並返回被移除的元素。
  • E set(int index, E element):用指定的元素替換列表中指定位置的元素,並返回原來位置的元素。
  • int size():返回列表中的元素數量。

由於 List 介面是有序的,並且提供了基於索引的訪問和操作方法,因此它非常適合用於需要頻繁進行插入、刪除和訪問操作的場景。

二.Set介面

Set 介面是 Java 集合框架中的一個重要介面,它繼承自 Collection 介面,用於表示不包含重複元素的集合。以下是對 Set 介面的詳細介紹:

1.介面定義與特點

  • 介面定義Set 介面是 Java 中的一個介面,它位於 java.util 包中,用於表示不包含重複元素的集合。

  • 特點

    1. 互異性Set 集合中的任何兩個元素都不相同,即每個元素只能出現一次。
    2. 無序性Set 集合中的元素是無序的,即集合不保證元素的任何特定順序。但請注意,某些 Set 的實現(如 LinkedHashSet)可能會保持元素的插入順序。
    3. 不包含重複元素Set 介面確保集合中不包含重複的元素。

2.主要實現類

Set 介面有幾個主要的實現類,包括但不限於:

  • HashSet:基於雜湊表實現,提供快速的元素插入和查詢操作,但不保證集合的迭代順序。
  • LinkedHashSetHashSet 的一個子類,它維護了一個執行於所有條目的雙向連結串列,從而按照插入順序來遍歷元素。
  • TreeSet:基於紅黑樹實現,能夠確保集合元素處於排序狀態。預設情況下,元素按照自然順序排序,但也可以指定自定義的比較器進行排序。

3.常用方法

Set 介面繼承了 Collection 介面的所有方法,並新增了一些自己的方法(雖然實際上在 Set 介面中並沒有定義額外的方法,因為 Set 本身就是 Collection 的一種特殊形式)。以下是一些常用的 Set 方法:

  • boolean add(E e):將指定的元素新增到集合中(如果尚未存在)。
  • boolean remove(Object o):從集合中刪除指定的元素(如果存在)。
  • boolean contains(Object o):檢查集合是否包含指定的元素。
  • int size():返回集合中的元素數量。
  • boolean isEmpty():檢查集合是否為空。
  • void clear():清空集合中的所有元素。
  • Iterator<E> iterator():返回一個迭代器,用於遍歷集合中的元素。

4.使用場景

Set 介面及其實現類在 Java 程式設計中有廣泛的應用場景,特別是在需要儲存不重複元素的集合時。例如,可以使用 Set 來跟蹤唯一的識別符號、在演算法中保持唯一元素的集合、或者作為資料結構的基礎來構建更復雜的資料結構等。

5.注意事項

  • 由於 Set 集合不保證元素的順序,因此在需要有序集合時,應該選擇如 LinkedHashSetTreeSet 這樣的實現類。
  • 在使用 TreeSet 時,如果元素型別沒有實現 Comparable 介面或者沒有提供自定義的比較器,那麼在新增元素時可能會丟擲 ClassCastExceptionNullPointerException
  • Set 介面的實現類(如 HashSet)通常不是同步的,如果在多執行緒環境中使用,需要外部同步或選擇同步的集合類(如 Collections.synchronizedSet)。

三.Queue介面

在Java中,Queue介面是一種用於表示佇列資料結構的介面,它位於java.util包中。佇列是一種先入先出(FIFO,First-In-First-Out)的資料結構,新元素被新增到佇列的末尾,而訪問元素(移除元素)則發生在佇列的開頭。Queue介面繼承自Collection介面,並擴充套件了佇列的操作。

非阻塞佇列是Queue介面的一種實現,它在操作佇列時不會阻塞當前執行緒。如果嘗試向已滿的非阻塞佇列中新增元素,或者從空佇列中移除元素,這些操作通常會立即返回一個結果或丟擲異常,而不是使執行緒等待。

非阻塞佇列實現:

1. LinkedList

  • 實現:基於雙向連結串列實現的ListDeque介面。
  • 特點:允許包含null元素,並且是非同步的。它實現了所有可選的列表操作,並允許包括null在內的所有元素。除了實現List介面外,LinkedList還提供了雙端佇列的功能,即可以從兩端新增和移除元素。
  • 使用場景:適用於需要頻繁在列表兩端進行插入和刪除操作的場景。由於它是基於連結串列的,因此在這些操作上通常比基於陣列的列表(如ArrayList)要快。

2. ArrayDeque

  • 實現:基於陣列的雙端佇列。
  • 特點:是一個先進先出(FIFO)的佇列,可以從兩端插入和移除元素。它是非阻塞的,且非同步的。與LinkedList相比,ArrayDeque在大多數佇列操作(特別是隨機訪問)上通常具有更好的效能,因為它減少了節點分配的開銷。
  • 使用場景:適用於需要高效能雙端佇列操作的場景。

3. PriorityQueue

  • 實現:基於優先順序堆的一個無界優先順序佇列。
  • 特點:元素的排序是根據其自然順序或構造佇列時提供的Comparator來確定的。佇列的頭部是佇列中優先順序最高的元素。PriorityQueue不允許null元素,且不是執行緒安全的。
  • 使用場景:適用於需要根據元素的優先順序來檢索元素的場景。例如,任務排程、事件處理等。

4. ConcurrentLinkedQueue

  • 實現:基於連結節點的無界執行緒安全佇列。
  • 特點:使用非阻塞演算法來實現高併發級別下的執行緒安全。它採用CAS(Compare-And-Swap)操作來確保執行緒安全,而不需要進行外部同步。ConcurrentLinkedQueue是FIFO的,並且是無界的,這意味著它可以無限期地增長。
  • 使用場景:適用於高併發環境下的非阻塞佇列操作。它避免了在多執行緒環境下使用LinkedList時可能遇到的同步問題。

總結

  • 如果你需要一個高效能的雙端佇列,並且不需要執行緒安全,那麼ArrayDeque可能是最好的選擇。
  • 如果你需要一個基於連結串列的佇列,並且需要頻繁在兩端進行插入和刪除操作,那麼LinkedList是合適的。
  • 如果你需要根據元素的優先順序來檢索元素,那麼PriorityQueue是最佳選擇。
  • 如果你在高併發環境下需要一個執行緒安全的非阻塞佇列,那麼ConcurrentLinkedQueue將是理想的選擇。

阻塞佇列實現:

在Java的併發程式設計中,ArrayBlockingQueueLinkedBlockingQueuePriorityBlockingQueueDelayQueueSynchronousQueueLinkedTransferQueueLinkedBlockingDeque是幾種常見的阻塞佇列實現,它們各自具有不同的特性和應用場景。以下是對這些佇列的詳細解析:

1. ArrayBlockingQueue

  • 特性:基於陣列結構的有界阻塞佇列,按FIFO(先進先出)原則對元素進行排序。
  • 應用場景:適合用於那些需要固定大小緩衝區的場景,如生產者-消費者模式中的緩衝區。
  • 執行緒安全性:透過內部鎖機制保證執行緒安全。
  • 阻塞行為:當佇列滿時,新增元素的操作會阻塞;當佇列空時,移除元素的操作會阻塞。

2. LinkedBlockingQueue

  • 特性:基於連結串列結構的阻塞佇列,按FIFO排序元素,吞吐量通常高於ArrayBlockingQueue
  • 應用場景:適用於高併發環境下的生產者-消費者模式,可作為任務佇列使用。
  • 執行緒安全性:內部使用鎖和條件變數保證執行緒安全。
  • 容量:可選容量,預設為Integer.MAX_VALUE,即幾乎無界。

3. PriorityBlockingQueue

  • 特性:基於陣列的優先順序阻塞佇列,無界,每次出隊都返回優先順序最高的元素。
  • 應用場景:適合需要按照優先順序順序處理任務的場景。
  • 排序:元素可以根據自然順序或構造時指定的Comparator進行排序。
  • 執行緒安全性:內部使用鎖和條件變數保證執行緒安全。

4. DelayQueue

  • 特性:無界阻塞佇列,用於放置實現了Delayed介面的物件,其中的元素只能在其指定的延遲時間到了之後才能從佇列中取走。
  • 應用場景:適合快取失效管理、任務排程等場景。
  • 執行緒安全性:內部使用PriorityQueue實現,並保證了執行緒安全。

5. SynchronousQueue

  • 特性:不儲存元素的阻塞佇列,每個插入操作必須等待另一個執行緒呼叫移除操作,否則插入操作一直處於阻塞狀態。
  • 應用場景:適用於傳遞性場景,如執行緒間的直接手遞手傳遞。
  • 執行緒安全性:內部使用鎖和條件變數保證執行緒安全。

6. LinkedTransferQueue

  • 特性:基於連結串列結構的無界阻塞TransferQueue,相比LinkedBlockingQueue增加了非阻塞的轉移方法。
  • 應用場景:適用於高併發環境下的複雜生產者-消費者場景,支援多個消費者。
  • 執行緒安全性:內部使用鎖和條件變數保證執行緒安全。

7. LinkedBlockingDeque

  • 特性:基於連結串列結構的雙端阻塞佇列,支援在兩端插入和移除元素。
  • 應用場景:適用於需要從佇列兩端進行操作的場景,如棧和佇列的混合使用。
  • 執行緒安全性:內部使用鎖和條件變數保證執行緒安全。

總結

以上七種阻塞佇列各有其特點和適用場景,開發者在選擇時應根據具體需求進行評估和選擇。例如,如果需要固定大小的緩衝區,則可以選擇ArrayBlockingQueue;如果需要無界且按優先順序排序的佇列,則可以選擇PriorityBlockingQueue;如果需要按延遲時間處理元素,則可以選擇DelayQueue等。同時,這些佇列都提供了執行緒安全的保證,使得在多執行緒環境下使用更加安全可靠。

四.Map介面

在Java中,HashMapTreeMapLinkedHashMapConcurrentHashMapIdentityHashMapHashtable都是用於儲存鍵值對的集合框架中的類,但它們各自具有不同的特性和用途。下面將簡要介紹每個類的特點和用途:

  1. HashMap
    • HashMap是基於雜湊表的Map介面的非同步實現。它允許使用null值和null鍵。
    • 它不保證對映的順序;特別是,它不保證該順序會隨時間保持不變。
    • 它是基於雜湊表的,因此其查詢、插入和刪除操作的平均時間複雜度為O(1)。
  2. TreeMap
    • TreeMap是基於紅黑樹(Red-Black tree)的NavigableMap實現。
    • 它能夠按照自然順序或者構造時所提供的Comparator進行排序。
    • TreeMap不允許使用null鍵;null值是可以的,但只能有一個。
    • 它保證了鍵的順序是升序的,無論是自然順序還是透過Comparator指定的順序。
  3. LinkedHashMap
    • LinkedHashMapHashMap的一個子類,它維護著一個執行於所有條目的雙重連結列表。
    • 這個連結列表定義了迭代器的遍歷順序,即按照元素被插入的順序或最近最少使用的順序(LRU)進行遍歷。
    • 它允許使用null鍵和null值。
  4. ConcurrentHashMap
    • ConcurrentHashMap是專為併發環境設計的,它實現了ConcurrentMap介面。
    • 它透過分段鎖(在Java 8及更高版本中透過CAS操作和synchronized塊最佳化)提供了比Hashtable更高的併發級別。
    • 它不允許使用null鍵和null值。
    • 它的迭代器提供了弱一致性的檢視,這反映了某一時間點或者迭代開始時的集合狀態,而不是實時的集合狀態。
  5. IdentityHashMap
    • IdentityHashMap使用==而不是equals()方法來比較鍵。
    • 這意味著對於兩個物件,即使它們的內容相同(即equals()方法返回true),但如果它們在記憶體中的位置不同,它們將被視為不同的鍵。
    • 它允許使用null鍵和null值。
  6. Hashtable
    • Hashtable是同步的,它實現了Map介面。
    • 它不允許使用null鍵和null值。
    • 它是基於雜湊表的,但與HashMap相比,它的所有方法都是同步的,這意味著它在多執行緒環境下是執行緒安全的,但可能會導致效能下降。
    • 它繼承自Dictionary類,是Java早期的一個集合類,現在通常建議使用ConcurrentHashMap來代替它,以獲得更好的併發效能。

總結:

  • 對於需要排序的Map,使用TreeMap
  • 對於需要保持插入順序的Map,使用LinkedHashMap
  • 對於併發環境下的Map,使用ConcurrentHashMap
  • 如果需要根據物件的記憶體地址(而非equals()方法)來比較鍵,使用IdentityHashMap
  • 對於需要執行緒安全的Map,但在Java 8及以上版本,推薦使用ConcurrentHashMap而不是Hashtable,因為ConcurrentHashMap提供了更好的併發效能和靈活性。

相關文章