微信公衆號【Java技術江湖】一位阿里Java工程師的技術小站
Java集合類學習總結
這篇總結是基於之前博客內容的一個整理和回顧。
這裏先簡單地總結一下,更多詳細內容請參考我的專欄:深入淺出Java核心技術
https://blog.csdn.net/column/details/21930.html
裏面有包括Java集合類在內的衆多Java核心技術系列文章。
以下總結不保證全對,如有錯誤,還望能夠指出,謝謝。
最後,如果想要更好地完成這部分內容的學習,建議大家還是去看一下原文。
Colletion,iterator,comparable
一般認爲Collection是最上層接口,但是hashmap實際上實現的是Map接口。iterator是迭代器,是實現iterable接口的類必須要提供的一個東西,能夠使用for(i : A) 這種方式實現的類型能提供迭代器,以前有一個enumeration,現在早棄用了。
List
List接口下的實現類有ArrayList,linkedlist,vector等等,一般就是用這兩個,用法不多說,老生常談。
ArrayList的擴容方式是1.5倍擴容,這樣擴容避免2倍擴容可能浪費空間,是一種折中的方案。 另外他不是線程安全,vector則是線程安全的,它是兩倍擴容的。
linkedlist是雙鏈表,並且很坑的一點是,Java裏的linkedlist自帶按索引訪問的api,結果我沒用過,面試的時候被問到答錯了,導致我美團直接涼涼= =。
除此之外還有一個copyonwritelist,用於線程安全的場景。
Map
map永遠都是重頭戲。
1 hashmap是數組和鏈表的組合結構,數組是一個Entry數組,entry是k-V鍵值對類型,所以一個entry數組存着很entry節點,一個entry的位置通過key的hashcode方法,再進行hash(移位等操作),最後與表長-1進行相與操作,其實就是取hash值到的後n - 1位,n代表表長是2的n次方。
2 hashmap的默認負載因子是0.75,閾值是16 * 0.75 = 12;初始長度爲16;
3 hashmap的增刪改查方式比較簡單,都是遍歷,替換。有一點要注意的是key相等時,替換元素,不相等時連成鏈表。
4 除此之外,1.8jdk改進了hashmap,當鏈表上的元素個數超過8個時自動轉化成紅黑樹,節點變成樹節點,以提高搜索效率和插入效率到logn。
5 還有一點值得一提的是,hashmap的擴容操作,由於hashmap非線程安全,擴容時如果多線程併發進行操作,則可能有兩個線程分別操作新表和舊錶,導致節點成環,查詢時會形成死鎖。chm避免了這個問題。
6 另外,擴容時會將舊錶元素移到新表,原來的版本移動時會有rehash操作,每個節點都要rehash,非常不方便,而1.8改成另一種方式,對於同一個index下的鏈表元素,由於一個元素的hash值在擴容後只有兩種情況,要麼是hash值不變,要麼是hash值變爲原來值+2^n次方,這是因爲表長翻倍,所以hash值取後n位,第一位要麼是0要麼是1,所以hash值也只有兩種情況。這兩種情況的元素分別加到兩個不同的鏈表。這兩個鏈表也只需要分別放到新表的兩個位置即可,是不是很酷。
7 最後有一個比較冷門的知識點,hashmap1.7版本鏈表使用的是節點的頭插法,擴容時轉移鏈表仍然使用頭插法,這樣的結果就是擴容後鏈表會倒置,而hashmap.1.8在插入時使用尾插法,擴容時使用頭插法,這樣可以保證順序不變。
CHM
concurrenthashmap也稍微提一下把,chm1.7使用分段鎖來控制併發,每個segment對應一個segmentmask,通過key的hash值相與這個segmentmask得到segment位置,然後在找到具體的entry數組下標。
所以chm需要維護多個segment,每個segment對應一段數組。分段鎖使用的是reetreetlock可重入鎖實現,查詢時不加鎖。
1.8則放棄使用分段鎖,改用cas+synchronized方式實現併發控制,查詢時不加鎖,插入時如果沒有衝突直接cas到成功爲止,有衝突則使用synchronized插入。
Set
set就是hashmap將value固定爲一個object,只存key元素,包裝成一個entry即可,其他不變。
Linkedhashmap
在原來hashmap基礎上將所有的節點依據插入的次序另外連成一個鏈表。用來保持順序,可以使用它實現lru緩存,當訪問命中時將節點移到隊頭,當插入元素超過長度時,刪除隊尾元素即可。
使用的時候先繼承linkedhashmap或者直接使用linkedhashmap作爲成員變量,然後重寫removeEldestEntry方法即可,注意傳入size參數,判斷當元素個數超過size時返回true,表示可以刪除就行了。
collections和Arrays工具類
兩個工具類分別操作集合和數組,可以進行常用的排序,合併等操作。
comparable和comparator
實現comparable接口可以讓一個類的實例互相使用compareTo方法進行比較大小,可以自定義比較規則,comparator則是一個通用的比較器,比較指定類型的兩個元素之間的大小關係。
這個東西還是很好用的,做算法題的時候經常會用到自定義的排序方式。
treemap和treeset
主要是基於紅黑樹實現的兩個數據結構,可以保證key序列是有序的,獲取sortedset就可以順序打印key值了。其中涉及到紅黑樹的插入和刪除,調整等操作,比較複雜,這裏就不細說了。
另外我們也可以獲取逆序的set集合。
其他
集合類要學的東西其實還很多,但是面試的東西可能就這麼多了把。當然可能還有一些遺漏,但是大部分我在面試中能遇到的問題都已經包含進去了。
▼更多精彩內容