java集合類介紹

發表於2021-05-26

集合類簡介

Java 集合,也稱作容器,主要是由兩大介面 (Interface) 派生出來的:CollectionMap

Collecton介面常用的子介面有:List介面、Set介面,和Queue;

Set介面常用的子類有:HashSet類、LinkedHashSet類。

Set、List和Map可以看做集合的三大類:

  • List集合是有序集合,集合中的元素可以重複,訪問集合中的元素可以根據元素的索引來訪問。
  • Set集合是無序集合,集合中的元素不可以重複,訪問集合中的元素只能根據元素本身來訪問(也是集合裡元素不允許重複的原因)。
  • Map集合中儲存Key-value對形式的元素,訪問時只能根據每項元素的key來訪問其value。

主幹,即Collection和Map

1、Collection是一個介面,是高度抽象出來的集合,它包含了集合的基本操作和屬性。Collection包含了List和Set兩大分支。

  • List是一個有序的佇列,每一個元素都有它的索引。第一個元素的索引值是0。List的實現類有LinkedList, ArrayList, Vector, Stack。
  • Set是一個不允許有重複元素的集合。Set的實現類有HastSet和TreeSet。HashSet依賴於HashMap,它實際上是通過HashMap實現的;TreeSet依賴於TreeMap,它實際上是通過TreeMap實現的。

2、Map是一個對映介面,即key-value鍵值對。Map中的每一個元素包含“一個key”和“key對應的value”。AbstractMap是個抽象類,它實現了Map介面中的大部分API。而HashMap,TreeMap,WeakHashMap都是繼承於AbstractMap。Hashtable雖然繼承於Dictionary,但它實現了Map介面。

3、接下來,再看Iterator。它是遍歷集合的工具,即我們通常通過Iterator迭代器來遍歷集合。我們說Collection依賴於Iterator,是因為Collection的實現類都要實現iterator()函式,返回一個Iterator物件。ListIterator是專門為遍歷List而存在的。

List

ArrayList

ArrayList 是一個用陣列實現的集合,支援隨機訪問,元素有序且可以重複。
每一個ArrayList都有一個初始容量(10),該容量代表了陣列的大小。隨著容器中的元素不斷增加,容器的大小也會隨著增加。在每次向容器中增加元素的同時都會進行容量檢查,當快溢位時,就會進行擴容操作。所以如果我們明確所插入元素的多少,最好指定一個初始容量值,避免過多的進行擴容操作而浪費時間、效率。

擴容:預設將擴容至原來容量的 1.5 倍:

# 右移一位,相當於1/2
int newCapacity = oldCapacity + (oldCapacity >> 1);

擴容之後是通過陣列的拷貝來確保元素的準確性的,所以儘可能減少擴容操作。 ArrayList 的最大儲存能力:Integer.MAX_VALUE

如果需要邊遍歷邊 remove ,必須使用 iterator。且 remove 之前必須先 next,next 之後只能用一次 remove。

ArrayList擅長於隨機訪問。同時ArrayList是非同步的。

查詢的效率高,插入和刪除需要移動元素效率低。

LinkedList

同樣實現List介面的LinkedList與ArrayList不同,ArrayList是一個動態陣列,而LinkedList是一個雙向迴圈連結串列。所以它除了有ArrayList的基本操作方法外還額外提供了get,remove,insert方法在LinkedList的首部或尾部。

由於實現的方式不同,LinkedList不能隨機訪問,它所有的操作都是要按照雙重連結串列的需要執行。在列表中索引的操作將從開頭或結尾遍歷列表(從靠近指定索引的一端)。這樣做的好處就是可以通過較低的代價在List中進行插入和刪除操作。

與ArrayList一樣,LinkedList也是非同步的。如果多個執行緒同時訪問一個List,則必須自己實現訪問同步。一種解決方法是在建立List時構造一個同步的List:

List list = Collections.synchronizedList(new LinkedList(...));

Vector

與ArrayList相似,但是Vector是同步的。所以說Vector是執行緒安全的動態陣列。它的操作與ArrayList幾乎一樣。

Stack

Stack繼承自Vector,實現一個後進先出的堆疊

Set

HashSet

HashSet 是一個沒有重複元素的集合。它是由HashMap實現的,不保證元素的順序(這裡所說的沒有順序是指:元素插入的順序與輸出的順序不一致),而且HashSet允許使用null 元素。HashSet是非同步的,如果多個執行緒同時訪問一個雜湊set,而其中至少一個執行緒修改了該set,那麼它必須保持外部同步。 HashSet按Hash演算法來儲存集合的元素,因此具有很好的存取和查詢效能。

HashSet的實現方式大致如下,通過一個HashMap儲存元素,元素是存放在HashMap的Key中,而Value統一使用一個Object物件。

LinkedHashSet

LinkedHashSet繼承自HashSet,其底層是基於LinkedHashMap來實現的,有序,非同步。LinkedHashSet集合同樣是根據元素的hashCode值來決定元素的儲存位置,但是它同時使用連結串列維護元素的次序。這樣使得元素看起來像是以插入順序儲存的,也就是說,當遍歷該集合時候,LinkedHashSet將會以元素的新增順序訪問集合的元素。

TreeSet

TreeSet是一個有序集合,其底層是基於TreeMap實現的,非執行緒安全。TreeSet可以確保集合元素處於排序狀態。TreeSet支援兩種排序方式,自然排序和定製排序,其中自然排序為預設的排序方式。當我們構造TreeSet時,若使用不帶引數的建構函式,則TreeSet的使用自然比較器;若使用者需要使用自定義的比較器,則需要使用帶比較器的引數。

Map

HashMap

以雜湊表資料結構實現,查詢物件時通過雜湊函式計算其位置,它是為快速查詢而設計的,其內部定義了一個hash表陣列(Entry[] table),元素會通過雜湊轉換函式將元素的雜湊地址轉換成陣列中存放的索引,如果有衝突,則使用雜湊連結串列的形式將所有相同雜湊地址的元素串起來,可能通過檢視HashMap.Entry的原始碼它是一個單連結串列結構。

Hashtable

Hashtable繼承Map介面,實現一個key-value對映的雜湊表。任何非空(non-null)的物件都可作為key或者value。如果相同的物件有不同的hashCode,對雜湊表的操作會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時複寫equals方法和hashCode方法,而不要只寫其中一個。

Hashtable是同步的。

LinkedHashMap

LinkedHashMap是HashMap的一個子類,它保留插入的順序,如果需要輸出的順序和輸入時的相同,那麼就選用LinkedHashMap。

LinkedHashMap是Map介面的雜湊表和連結列表實現,具有可預知的迭代順序。此實現提供所有可選的對映操作,並允許使用null值和null鍵。此類不保證對映的順序,特別是它不保證該順序恆久不變。

LinkedHashMap實現與HashMap的不同之處在於,後者維護著一個執行於所有條目的雙重連結列表。此連結列表定義了迭代順序,該迭代順序可以是插入順序或者是訪問順序。

由於LinkedHashMap需要維護元素的插入順序,因此效能略低於HashMap的效能,但在迭代訪問Map裡的全部元素時將有很好的效能,因為它以連結串列來維護內部順序。

TreeMap

TreeMap(主要是排序) 是一個有序的key-value集合,非同步,基於紅黑樹(Red-Black tree)實現,每一個key-value節點作為紅黑樹的一個節點。TreeMap儲存時會進行排序的,會根據key來對key-value鍵值對進行排序,其中排序方式也是分為兩種,一種是自然排序,一種是定製排序,具體取決於使用的構造方法。

相互區別

Vector和ArrayList

  1. vector是執行緒同步的,所以它也是執行緒安全的,而arraylist是執行緒非同步的,是不安全的。如果不考慮到執行緒的安全因素,一般用arraylist效率比較高。
  2. ArrayList 和Vector是採用陣列方式儲存資料,此陣列元素數大於實際儲存的資料以便增加和插入元素,都允許直接序號索引元素,但是插入資料要設計到陣列元素移動 等記憶體操作,所以索引資料快插入資料慢,Vector由於使用了synchronized方法(執行緒安全)所以效能上比ArrayList要 差,LinkedList使用雙向連結串列實現儲存,按序號索引資料需要進行向前或向後遍歷,但是插入資料時只需要記錄本項的前後項即可,所以插入數度較快!

ArrayList和LinkedList

  1. ArrayList是實現了基於動態陣列的資料結構,LinkedList基於雙向連結串列的資料結構。
  2. 對於隨機訪問get和set,ArrayList覺得優於LinkedList,因為LinkedList要移動指標。
  3. 對於新增和刪除操作add和remove,LinedList比較佔優勢,因為ArrayList要移動資料。(擴容時需要複製操作)

HashMap與TreeMap

  1. HashMap通過hashcode對其內容進行快速查詢,而TreeMap中所有的元素都保持著某種固定的順序,如果你需要得到一個有序的結果你就應該使用TreeMap(HashMap中元素的排列順序是不固定的)。HashMap中元素的排列順序是不固定的)。
  2. HashMap通過hashcode對其內容進行快速查詢,而TreeMap中所有的元素都保持著某種固定的順序,如果你需要得到一個有序的結果你就應該 使用TreeMap(HashMap中元素的排列順序是不固定的)。集合框架”提供兩種常規的Map實現:HashMap和TreeMap (TreeMap實現SortedMap介面)。
  3. 在Map 中插入、刪除和定位元素,HashMap 是最好的選擇。但如果您要按自然順序或自定義順序遍歷鍵,那麼TreeMap會更好。使用HashMap要求新增的鍵類明確定義了hashCode()和 equals()的實現。這個TreeMap沒有調優選項,因為該樹總處於平衡狀態。

HashTable與HashMap

  1. 歷史原因:Hashtable是基於陳舊的Dictionary類的,HashMap是Java 1.2引進的Map介面的一個實現。
  2. 同步性:Hashtable是執行緒安全的,也就是說是同步的,而HashMap是執行緒序不安全的,不是同步的
  3. 值:只有HashMap可以讓你將空值作為一個表的條目的key或value

相關文章