【導讀】[開始]
(包括集合接口,類簡述;常用散列集,樹集兩種數據結構;視圖;線程安全集合)
Java中集合,從元素形式上來區分,分爲’列表’(元素是單個形式)和’映射’(元素是鍵值對形式)。
【導讀】[結束]
###1 接口總覽
###2 類總覽
###3 接口簡述
接口名 | 簡述 |
---|---|
SortedSet; SortedMap<K, V> |
這兩個接口,會提供用於排序的比較器對象。 這兩個接口定義了可以得到集合子集視圖的方法。 |
NavigableSet; NavigableMap<K, V> |
包含一些用於搜索和遍歷有序集和映射的方法。 TreeSet 和 TreeMap實現了這些接口。 |
Iterator; ListIterator |
hasNext(); next(); hasPrevious(); previous(); add();等。 定義了一個方法用於在迭代器位置前面增加一個元素。 |
Iterable | 定義3個方法: iterator()返回迭代器對象。 forEach(Consumer<? super T> action)遍歷。 spliterator()並行遍歷。 |
Queue; Deque |
隊列接口。 |
RandomAccess | 標記接口,可根據索引隨機訪問元素。 |
###4 類簡述
類名 | 數據結構 | 效率 | 簡述 |
---|---|---|---|
LinkedList | 雙向鏈表 | 添加,刪除元素效率高; 獲取元素效率低,遍歷查找耗時。 |
get(i),當i>(1/2)size,從尾端進行遍歷。 |
ArrayList | 數組 | 添加,刪除效率低,部分元素做整體移動以保證元素存儲的物理連續性,耗時。 獲取元素效率高。 |
可動態拓展。 |
HashSet | 哈希表 | 效率較高。 | 元素不可重複。 |
LinkedHashSet | 哈希表和雙鏈表的結合體。 | 相較於HashSet,效率稍低。 | 按照插入順序進行迭代,即迭代輸出順序與插入順序一致。 元素不可重複。 實現方式是對LinkedHashMap<K, V>的適配轉換。 |
EnumSet | 二進制序列來唯一標記對應枚舉值 | 效率非常高。 | 底層並不是直接存放枚舉對象,是用二進制位向量來存放,存儲緊湊,並且高效。 |
TreeSet | 紅黑樹 | 添加元素時對元素進行排序。相對耗時。 | 元素會被排序。 元素不重複。 |
PriorityQueue | 完全二叉樹,即堆結構,具體應該是小頂堆 | 添加元素耗時。刪除最小元素效率高。 | 可高效刪除最小元素的集合。 |
**ArrayDeque ** | 循環數組實現的雙端隊列 | 效率上具有和數組類似的特點。 | 由於可從兩端來操作隊列中的元素。故即可當做隊列使用,也可以當成棧來使用。 |
HashMap | 哈希表 | 類比HashSet | 元素爲鍵值對。 |
LinkedHashMap | 哈希表和雙鏈表的結合體 | 類比LinkedHashSet | 元素爲鍵值對。 |
TreeMap | 紅黑樹 | 類比TreeSet | 元素爲鍵值對。 |
EnumMap | 同EnumSet | 效率高 | 值屬於枚舉類型的映射表。 |
WeakHashMap | 哈希表 | 效率較高 | 鍵值對的key是弱引用。(鍵值對被使用一次後,對應key被刪除回收。) |
IdentityHashMap | 哈希表 | 效率較高 | 判等時對key引用相等性判等,用 == 比較key的相等性。 |
EnumSet/EnumMap說明:
(由於枚舉類型的所有值的個數是有限的,因此可以用二進制序列來唯一表示,如一個枚舉有{a,b,c,d}四個值,這裏就用4位二進制數表示,現在只有a、c、d這三個值,因此可以表示爲1011,1表示該枚舉值在集合中,0表示不在集合種;枚舉值在枚舉類型中是有序號的,就是按照其定義順序排列的。
###5 散列集(哈希表)
- 數據結構特點:
<1>數據結構:整體看做數組,每個數組元素爲鏈表。(JavaSE8 桶滿時,從鏈表變爲平衡二叉樹。)
<2>效率:查找元素效率高。 - 哈希表知識:
<1>哈希碼(散列碼):根據哈希函數,爲每個對象生成一個值,叫做哈希碼。(JavaSE對HashCode約束:兩個對象相同,hashCode一定相同;hashCode不同,兩個對象一定不相同;hashCode相同,兩個對象不一定相同。)
<2>哈希碼作用:當對象存儲在哈希表中(如Hashtable,HashMap,HashSet)時,哈希表中查找對象時,先依據HashCode確定對象所在的鏈表(HashCode值對數組長度取餘,確定鏈表索引),再依據equals方法在鏈表中確定對象是否存在。
<3>哈希衝突:向哈希表插入元素時,根據HashCode找到了所在的鏈表。卻發現鏈表已經被佔滿,這種情況叫做哈希衝突。解決哈希衝突,需要再散列。
<4>再散列:再散列需要創建一個桶數更多的表,並將所有的元素都插入到新表中,廢棄原來的表。
<5>裝填因子:決定何時進行再散列的依據。默認值爲0.75,表示表中75%的位置已經被填入元素,這個表就會用雙倍的桶數進行自動再散列。
<6>HashMap提供了三個構造函數:
HashMap():
構造一個具有默認初始容量 (16) 和默認加載因子 (0.75) 的空 HashMap。
HashMap(int initialCapacity):
構造一個帶指定初始容量和默認加載因子 (0.75) 的空 HashMap。
HashMap(int initialCapacity, float loadFactor):
構造一個帶指定初始容量和加載因子的空 HashMap。
###6 樹集(主要是二叉樹)
- 數據結構特點:
<1>數據結構:元素會進行排序。
<2>效率:查找元素效率高。插入元素效率相對哈希表稍慢。 - 樹集知識:
- TreeSet和TreeMap都是紅黑樹結構,具體數據結構原理下一篇總結。
###7 視圖
7.1視圖–對映射集合遍歷的一種手段
❶ 對於列表集合來說(即AbstractCollection的所有子類集合),遍歷元素可以使用以下方式:
treeSet.forEach(item -> System.out.println(item));//forEach
treeSet.iterator();//使用迭代器
treeSet.stream();//stream()
❷對於映射集合來說(即AbstractMap的所有子類集合),Java中並不認爲映射本身是一種集合,對"映射"集合遍歷,首先需要得到映射的視圖,然後再對視圖進行操作。
❸視圖是什麼?視圖是實現了Collection接口,或它的某個子接口的對象,注意是對象,返回的視圖並不是集合,對象裏的方法是對原映射進行操作的。
❹映射對應於3種視圖。
視圖 | 類型 | 描述 |
---|---|---|
鍵集視圖 | Set keySet() | keySet是實現Set接口的另外某個類的對象,不是HashSet或TreeSet |
值集視圖 | Collection values() | 值的集合視圖 |
鍵/值對集視圖 | Set<> entrySet() | 泛型限定爲Map.Entry接口的類的對象 |
❺轉換爲視圖後,就是裝換爲了Collection接口的某個實現類的對象,就可以使用Collection中的3種方式進行變遍歷操作。
Iterator<Entry<String, String>> iterator = map.entrySet().iterator();//迭代器
Stream<Entry<String, String>> set = map.entrySet().stream();//forEach()
map.entrySet().forEach(item -> System.out.println(item.getKey() + "->" + item.getValue()));//stream()
❻注意:只能對這些視圖進行元素刪除操作,而不能進行增加元素操作。刪除操作,會對應更改原來的映射集。
#####7.2視圖–構造線程安全的集合視圖
常規的集合都是非線程安全的集合。 類庫的設計者使用視圖來確常規集合的線程安全。
java.util.Collections下的一組方法可以構造線程安全的集合視圖,直接對構造出來的線程安全的集合視圖進行get和put操作,可保證是同步的操作且,線程安全。可對視圖的做get,put,remove,replace操作,可保證是同步的方法,線程安全。。
static <T> Collection<T> synchronizedCollection(Collection<T> c);
static <T> Set<T> synchronizedSet(Set<T> s);
static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s);
static <T> NavigableSet<T> synchronizedNavigableSet(NavigableSet<T> s);
static <T> List<T> synchronizedList(List<T> list);
static <K,V> Map<K,V> synchronizedMap(Map<K,V> m);
static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m);
static <K,V> NavigableMap<K,V> synchronizedNavigableMap(NavigableMap<K,V> m);
#####7.3 視圖–侷限性
視圖還有其他的一些應用,包括獲取子範圍視圖;生成不可修改的視圖;生成受檢查視圖等等。但是視圖有很多侷限性,通常對一些視圖可讀,而不可修改。
###*8 java.util.concurrent.包中的線程安全集合
java.util.concurrent包中也提供了一些線程安全的集合的實現。
常用的有:
ConcurrentHashMap<K, V>//映射
ConcurrentSkipListMap<K, V>//有序集
ConcurrentSkipListSet<E>//有序集
ConcurrentLinkedQueue<E>//無邊界非阻塞隊列
......
詳細的總結,會在後續的多線程併發這一塊。