標籤:link lock 封裝類 隨機 允許 讀寫 get dha 個數
集合整體架構圖
各集合架構的概述
1. Collection(常用List和Set,不常用Queue和Vector),單元素集合。
2. Map(常用HashMap和TreeMap,不常用HashTable),key-value映射關係。
3. Iterator(迭代器)
4. Comparable和Comparator比較子
5. Collections和Arrays工具類
Java中結合和數組的比較
1. 數組的長度在初始化時指定,只能儲存定長的資料。
而集合可以儲存不確定長度的資料。同時可以儲存具有映射關係的資料(即關聯陣列,索引值對key-value)。
2. 資料元素既可以是基本類型的值,也可以是對象,集合只能儲存對象(實際上是只儲存對象的引用變數),基礎資料型別 (Elementary Data Type)的變數要轉換成對應的封裝類才能放入集合中。
常用集合特性概述List系
List的特點:元素有放入順序,元素可以重複。
List介面的三個實作類別:ArrayList、LinkedList和Vector。
ArrayList、LinkedList和Vector的區別
LinkedList:底層是基於鏈表實現,鏈表記憶體是散亂的,每一個元素儲存本身記憶體位址的同時也儲存下一個元素的記憶體位址。鏈表增刪快,尋找慢。
ArrayList和Vector:兩者底層都是基於數組實現的,查詢快,增刪慢。兩者之間的區別是ArrayList是線程非安全的,效率高;而Vector是安全執行緒的,效率低。
ArrayList的初始化大小是10,擴容策略是1.5倍原元素數量的大小。
選擇標準
如果涉及到“動態數組”、“棧”、“隊列”、“鏈表”等結構,應該考慮用List,具體選擇哪個List實作類別,根據下面的標準來取捨:
1. 對於需要快速插入、刪除元素,應該使用LinkedList。
2. 對於需要快速隨機訪問元素,應該使用ArrayList。
3. 對於“單線程環境”或者“多線程環境,但List僅僅只會被單個線程操作”,此時應該使用非同步的類(如ArrayList)。對於“多線程環境,且List可能同時被多個線程操作”,此時,應該使用同步的類(如Vector)。
Set系
Set的特點:元素放入無順序,元素不可重複。
Set介面的三個實作類別:LinkedSet、HashSet和LinkedHashSet。
HashSet(底層是通過HashMap實現)底層通過HashCode和equals去重。
HashSet中判斷集合元素相等
兩個對象比較 具體分為如下四個情況:
1.如果有兩個元素通過equal()方法比較返回false,且它們的hashCode()方法返回不相等,HashSet將會把它們儲存在不同的位置。
2.如果有兩個元素通過equal()方法比較返回true,但它們的hashCode()方法返回不相等,HashSet將會把它們儲存在不同的位置。
3.如果兩個對象通過equals()方法比較不相等,但hashCode()方法比較相等,HashSet將會把它們儲存在相同的位置,在這個位置以鏈表式結構來儲存多個對象。這是因為當向HashSet集合中存入一個元素時,HashSet會調用對象的hashCode()方法來得到對象的hashCode值,然後根據該hashCode值來決定該Object Storage Service在HashSet中儲存位置。
4.如果有兩個元素通過equal()方法比較返回true,且它們的hashCode()方法返回true,HashSet將不予添加。
HashSet判斷兩個元素相等的標準:兩個對象通過equals()方法比較相等,並且兩個對象的hashCode()方法傳回值也相等。
注意:HashSet是根據元素的hashCode值來快速定位的,如果HashSet中兩個以上的元素具有相同的hashCode值,將會導致效能下降。所以如果重寫類的equals()方法和hashCode()方法時,應盡量保證兩個對象通過hashCode()方法傳回值相等時,通過equals()方法比較返回true。
LinkedHashSet類
LinkedHashSet是HashSet對的子類,也是根據元素的hashCode值來決定元素的儲存位置,同時使用鏈表維護元素的次序,使得元素是以插入的順序來儲存的。當遍曆LinkedHashSet集合裡的元素時,LinkedHashSet將會按元素的添加順序來訪問集合裡的元素。但是由於要維護元素的插入順序,在效能上略低與HashSet,但在迭代訪問Set裡的全部元素時有很好的效能。
注意:LinkedHashSet依然不允許元素重複,判斷重複標準與HashSet一致。
補充:HashSet的實質是一個HashMap。HashSet的所有集合元素,構成了HashMap的key,其value為一個靜態Object對象。因此HashSet的所有性質,HashMap的key所構成的集合都具備。可以參考後續文章中HashMap的相關內容進行比對。
TreeSet類
TreeSet是SortedSet介面的實作類別,正如SortedSet名字所暗示的,TreeSet可以確保集合元素處於排序狀態。此外,TreeSet還提供了幾個額外的方法。
1 comparator():返回對此 set 中的元素進行排序的比較子;如果此 set 使用其元素的自然順序,則返回null。2 first():返回此 set 中當前第一個(最低)元素。3 last(): 返回此 set 中當前最後一個(最高)元素。4 lower(E e):返回此 set 中嚴格小於給定元素的最大元素;如果不存在這樣的元素,則返回 null。5 higher(E e):返回此 set 中嚴格大於給定元素的最小元素;如果不存在這樣的元素,則返回 null。6 subSet(E fromElement, E toElement):返回此 set 的部分視圖,其元素從 fromElement(包括)到 toElement(不包括)。7 headSet(E toElement):返回此 set 的部分視圖,其元素小於toElement。8 tailSet(E fromElement):返回此 set 的部分視圖,其元素大於等於 fromElement。
Map系
Map的特點:儲存的元素是索引值對,在JDK1.8版本中是Node,在老版本中是Entry。
Map介面有四個實作類別:HashMap、HashTable、LinkedHashMap和ConcurrentHashMap。
HashMap類
HashMap是非安全執行緒,高效,支援null的key和value,底層實現是數組和鏈表,通過HashCode方法和equals方法保證鍵的唯一性。
如果需要使用安全執行緒的Map可以有兩種方式:
1. 採用HashTable
2. 採用Collections.synchronizedMap(hashMap)方式進行同步。
解決衝突主要有三種方法:定址法、拉鏈發和再散列發。
HashMap是採用拉鏈法解決雜湊衝突的,拉鏈法是將相同hash值的對象組成一個鏈表放在hash值對應的槽位。
HashMap的初始化大小是16,擴充因子是0.75,擴容策略是2倍原容量的大小。
put的大致流程
1. 通過hashCode方法計算出key的hash值
2. 通過hash%length計算出儲存在table中的index(源碼中是使用hash&(length-1),這樣結果相同,但是更快)。
3. 如果此時table[index]的值為空白,那麼就直接儲存,如果不為空白那麼就連結到這個數所在的鏈表的頭部。(在JDK1.8中,如果鏈表長度大於8就轉化成紅/黑樹狀結構)
get的大致流程
1. 通過通過hashCode方法計算出key的hash值
2. 通過hash%length計算出儲存在table中的index(源碼中是使用hash&(length-1),這樣結果相同,但是更快)。
3. 遍曆table[index]所在的鏈表,只有當key與該節點中的key的值相同時才取出。
ConcurrentHashMap類
是從JDK1.5之後提供的一個HashTable的替代實現,採用分段鎖機制,一個map中的元素分成很多的segment,通過lock機制可以對每個segment加讀寫鎖,從而提高map的效率,底層實現採用數組+鏈表+紅/黑樹狀結構的儲存結構。
HashTable類
安全執行緒,低效,不支援null的key和value。
SortedMap類
有一個實作類別:TreeMap會儲存放入元素的順序。
Java基礎加強之集合