Java集合
Collection是集合List,Set,Queue最基本的接口;
Map是映射表最基本的接口;
瞭解如下基本數據結構
1.數組:增刪慢,支持隨機查找;
2.鏈表:增刪快,不支持隨機查找,只能順序訪問;
3.哈希表:查詢速度快,在拉鍊法種查詢速度取決於鏈表長度,無序;
4.隊列:可以兩端出入,可以用鏈表和數組實現;
有序無序是指插入順序:先插在前,後插在後;
一.List
1.ArrayList
1.底層是數組;
2.是有序的,可重複;
3.線程不安全;
4.擴容1.5倍;
2.Vector
1.底層是數組;
2.有序,可重複;
3.線程安全,因爲支持線程同步,訪問速度就下來了;
4.擴容2倍;
3.LinkedList
1.底層是雙向鏈表:可以當作隊列,雙向隊列,堆,棧使用;
2.有序,可重複;
3.線程不安全;
二.Set
1.HashSet
1.底層是哈希表;key值通過hashCode()方法得到hash值,也就是數組下標,如果hash值相同,再通過equals方法比較兩個對象是否相同,相同則覆蓋,不同則放入鏈表中;
2.無序,不可重複;
3.存取速度快;
注:哈希相同就會產生哈希衝突,兩種方法:哈希值下移,和拉鍊法(HashMap的時候會介紹);
2.TreeSet
1.底層是二叉樹;
2.有序,不可重複;
3.按照指定的順序排序,Integer和String可以按默認的TreeSet順序排序,對於自定義的類必須實現Comparable接口,並重寫compare()函數;
4.底層實現是TreeMap;
3.LinkedHashSet
1.無序;
2.繼承HashSet,方法操作同HashSet,底層是LinkedHashMap實現;
三.Map
1.HashMap
1.無序,鍵值不可重複,值可重複;
2.底層哈希表;
3.線程不安全;
4.允許鍵值爲null,擴容2倍;
5.實現結構:
- 數組+鏈表——Entry[] table;Entry是鏈表,存儲有:key值,hash值,value和next;
原理很簡單: key值通過hashCode()方法得到hash值,也就是數組下標,如果hash值相同,再通過equals方法比較兩個對象是否相同,相同則覆蓋,不同則放入鏈表中;放入鏈表的時候 是插在頭部而不是尾部;
- 四個參數
爲甚麼capacity必須保證2的n次方?
得到數組下標需要hash%capacity,我們比較兩端代碼
hash%capacity
hash%(capacity-1)可以發現,當capacity爲2的n次方時,此操作和取模一摸一樣;但在計算計算機中位運算的速度更快;所以採用下面的與運算; - java8實現——數組+鏈表+紅黑樹
查詢速度取決於鏈表長度,當鏈表長度個數超過8個以後會轉換成紅黑樹,時間複雜度可以從O(n)降到O(logn)
2.HashTable
1.底層哈希表;
2.鍵值不可重複,值可重複,無序;
3.線程安全;
4.鍵和值都不能爲null;
5.HashTable是遺留類,繼承自Dictionary類,雖然是線程安全,但併發性不如ConcurrentHashMap;
3.TreeMap
1.底層二叉樹;
2.有序,鍵值不可重複,值可重複;
3.繼承自SortedMap,默認對鍵進行升序排序,可以自定義Comparable接口,重定義排序規則;底層實現是紅黑樹(屬於排序樹的一種),加進去之後使用中序遍歷就可以得到由小到大的順序;
4.添加節點
a以根節點當前節點開始搜索。
b拿新節點的值和當前節點的值比較。
c如果新節點的值更大,則以當前節點的右子節點作爲新的當前節點;如果新節點的值更小,則以當前節點的左子節點作爲新的當前節點。
d重複 2、3 兩個步驟,直到搜索到合適的葉子節點爲止。
e將新節點添加爲第 4 步找到的葉子節點的子節點;如果新節點更大,則添加爲右子節點;否則添加爲左子節點。
4.LinkedHashMap
1.HashMap的一個子類,保存了插入的順序,使用Iterator進行迭代時,得到數據跟插入的順序一樣;
2.哈希表通過Iterator得到的數據就是無序的,比如HashSet,HashMap,因爲他們插入的時候沒有像數組一樣記錄順序;
3.底層是HashMap和雙向鏈表合二爲一;
如何實現,雙向鏈表的節點圖如下,before,after和next的區別是前者可以連接不同hash之間的鏈表,只要將數據put到雙向鏈表中,就可以實現按插入順序訪問該結構;
4.該集合有兩種遍歷方式,
訪問順序遍歷: 每次訪問完map中的元素後,會將該元素置入map的最後一位;
插入順序遍歷: 按插入時的順序遍歷
圖片取自https://blog.csdn.net/a724888/article/details/80290276
圖片取自https://blog.csdn.net/fengdongsuixin/article/details/95758243
5. 留個問題?LinkedHashMap如何實現LRU緩存?
5.ConcurrentHashMap
- ConcurrentHashMap 是一個 Segment 數組,Segment 通過繼承ReentrantLock 來進行加鎖,所以每次需要加鎖的操作鎖住的是一個 segment,這樣只要保證每個 Segment 是線程安全的,也就實現了全局的線程安全。
- concurrencyLevel:segment數。默認是 16,
也就是說 ConcurrentHashMap 有 16 個 Segments,所以理論上,這個時候,最多可以同時支持 16 個線程併發寫,只要它們的操作分別分佈在不同的 Segment 上。這個值可以在初始化的時候設置爲其他值,但是一旦初始化以後,它是不可以擴容的。
- Java8引入紅黑樹,同HashMap一樣;