List,Set,Queue,Map介面
一.List介面
List
介面是 Java 集合框架中的一個重要介面,它繼承自 Collection
介面。List
介面表示一個有序的集合,其中的元素可以重複。這意味著在 List
中,每個元素都有一個特定的索引位置,我們可以透過這個索引來訪問或操作元素。
List
介面的主要特點包括:
- 有序性:
List
集合中的元素是按照它們被插入的順序來儲存的。可以透過索引來訪問集合中的元素。 - 允許重複元素:與
Set
介面不同,List
允許儲存重複的元素。 - 提供額外的方法:除了從
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
包中,用於表示不包含重複元素的集合。 -
特點
:
- 互異性:
Set
集合中的任何兩個元素都不相同,即每個元素只能出現一次。 - 無序性:
Set
集合中的元素是無序的,即集合不保證元素的任何特定順序。但請注意,某些Set
的實現(如LinkedHashSet
)可能會保持元素的插入順序。 - 不包含重複元素:
Set
介面確保集合中不包含重複的元素。
- 互異性:
2.主要實現類
Set
介面有幾個主要的實現類,包括但不限於:
HashSet
:基於雜湊表實現,提供快速的元素插入和查詢操作,但不保證集合的迭代順序。LinkedHashSet
:HashSet
的一個子類,它維護了一個執行於所有條目的雙向連結串列,從而按照插入順序來遍歷元素。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
集合不保證元素的順序,因此在需要有序集合時,應該選擇如LinkedHashSet
或TreeSet
這樣的實現類。 - 在使用
TreeSet
時,如果元素型別沒有實現Comparable
介面或者沒有提供自定義的比較器,那麼在新增元素時可能會丟擲ClassCastException
或NullPointerException
。 Set
介面的實現類(如HashSet
)通常不是同步的,如果在多執行緒環境中使用,需要外部同步或選擇同步的集合類(如Collections.synchronizedSet
)。
三.Queue介面
在Java中,Queue
介面是一種用於表示佇列資料結構的介面,它位於java.util
包中。佇列是一種先入先出(FIFO,First-In-First-Out)的資料結構,新元素被新增到佇列的末尾,而訪問元素(移除元素)則發生在佇列的開頭。Queue
介面繼承自Collection
介面,並擴充套件了佇列的操作。
非阻塞佇列是Queue
介面的一種實現,它在操作佇列時不會阻塞當前執行緒。如果嘗試向已滿的非阻塞佇列中新增元素,或者從空佇列中移除元素,這些操作通常會立即返回一個結果或丟擲異常,而不是使執行緒等待。
非阻塞佇列實現:
1. LinkedList
- 實現:基於雙向連結串列實現的
List
和Deque
介面。 - 特點:允許包含
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的併發程式設計中,ArrayBlockingQueue
、LinkedBlockingQueue
、PriorityBlockingQueue
、DelayQueue
、SynchronousQueue
、LinkedTransferQueue
和LinkedBlockingDeque
是幾種常見的阻塞佇列實現,它們各自具有不同的特性和應用場景。以下是對這些佇列的詳細解析:
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中,HashMap
、TreeMap
、LinkedHashMap
、ConcurrentHashMap
、IdentityHashMap
和Hashtable
都是用於儲存鍵值對的集合框架中的類,但它們各自具有不同的特性和用途。下面將簡要介紹每個類的特點和用途:
- HashMap
HashMap
是基於雜湊表的Map介面的非同步實現。它允許使用null值和null鍵。- 它不保證對映的順序;特別是,它不保證該順序會隨時間保持不變。
- 它是基於雜湊表的,因此其查詢、插入和刪除操作的平均時間複雜度為O(1)。
- TreeMap
TreeMap
是基於紅黑樹(Red-Black tree)的NavigableMap實現。- 它能夠按照自然順序或者構造時所提供的Comparator進行排序。
TreeMap
不允許使用null鍵;null值是可以的,但只能有一個。- 它保證了鍵的順序是升序的,無論是自然順序還是透過Comparator指定的順序。
- LinkedHashMap
LinkedHashMap
是HashMap
的一個子類,它維護著一個執行於所有條目的雙重連結列表。- 這個連結列表定義了迭代器的遍歷順序,即按照元素被插入的順序或最近最少使用的順序(LRU)進行遍歷。
- 它允許使用null鍵和null值。
- ConcurrentHashMap
ConcurrentHashMap
是專為併發環境設計的,它實現了ConcurrentMap介面。- 它透過分段鎖(在Java 8及更高版本中透過CAS操作和synchronized塊最佳化)提供了比Hashtable更高的併發級別。
- 它不允許使用null鍵和null值。
- 它的迭代器提供了弱一致性的檢視,這反映了某一時間點或者迭代開始時的集合狀態,而不是實時的集合狀態。
- IdentityHashMap
IdentityHashMap
使用==而不是equals()方法來比較鍵。- 這意味著對於兩個物件,即使它們的內容相同(即equals()方法返回true),但如果它們在記憶體中的位置不同,它們將被視為不同的鍵。
- 它允許使用null鍵和null值。
- Hashtable
Hashtable
是同步的,它實現了Map介面。- 它不允許使用null鍵和null值。
- 它是基於雜湊表的,但與
HashMap
相比,它的所有方法都是同步的,這意味著它在多執行緒環境下是執行緒安全的,但可能會導致效能下降。 - 它繼承自Dictionary類,是Java早期的一個集合類,現在通常建議使用
ConcurrentHashMap
來代替它,以獲得更好的併發效能。
總結:
- 對於需要排序的Map,使用
TreeMap
。 - 對於需要保持插入順序的Map,使用
LinkedHashMap
。 - 對於併發環境下的Map,使用
ConcurrentHashMap
。 - 如果需要根據物件的記憶體地址(而非equals()方法)來比較鍵,使用
IdentityHashMap
。 - 對於需要執行緒安全的Map,但在Java 8及以上版本,推薦使用
ConcurrentHashMap
而不是Hashtable
,因為ConcurrentHashMap
提供了更好的併發效能和靈活性。