Java集合框架體系(超詳細)


集合框架體系

總體的體系圖:

 

在學習體系之前先了解一下迭代器(Iterator):迭代器是一種設計模式,它是一個對象,它可以遍歷並選擇序列中的對象,而開發人員不需要了解該序列的底層結構。迭代器通常被稱為“輕量級”對象,因為創建它的代價小。對於集合的輸出,有foreach和iterator,iterator更加的常用。

https://www.cnblogs.com/lxqiaoyixuan/p/7156944.html

其次再了解一下hash和hashcode

hash函數特性:

調用hashcode()方法計算hash

hash表(散列表):https://www.jianshu.com/p/a89e9487a06c

hash和hashcode:https://blog.csdn.net/m0_37700275/article/details/82800590#commentBox

其次了解一下比較器(在涉及到比較的時候會用到比較器):在很多基本數據類型和引用數據類型中基本上都存在着排序的方法,但是對於自定義的類要實現排序,無法使用系統內部的類(比如Arrays.sort())實現數組排序或者比較需求,是因為沒有提供比較規則,所以提供了一個comparable接口來定義比較規則

comparable:使用需要繼承comparable接口並實現compareto方法,其中compareto方法中如果當前數據比傳入的對象小則返回負數,如果大於那么返回正數,相等則返回0。下面實現一個最基本的比較:

comparator:是一種補救措施,當系統開發完整又需要添加排序功能的時候,但是又不允許修改類的結構(無法實現comparable接口了),這個時候會使用comparator。在挽救中,想要排序的類(這里用Person類)和comparator沒有任何直接關系,關系如圖(PersonComparator是一個排序規則類):

 

下面來實現一個基本的comparator排序:

首先定義排序規則類:

然后再利用arrays的sort方法傳入排序規則類實現排序:

除非在萬不得已的情況下使用comparator,正常情況下還是使用comparable。

comparable和comparator面試題:請解釋comparator和comparable的區別?

comparable是在類定義的實現的父接口,主要用於定義排序規則,里面只有一個compareto方法。

comparator是挽救的操作,需要設置單獨的比較器規則類實現排序,里面有compare()方法。

最后了解一下二叉樹和紅黑樹:在這之前給出一個數據結構可視化的學習網站:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

各種樹的結構:https://www.jianshu.com/p/3585745cc45b

二叉樹的遍歷:前,中,后只是指父節點遍歷的順序,前序就是 父節點->左子樹->右子樹,中序是 左子樹->父節點->右子樹,后序是 左子樹 -> 右子樹 ->父節點。

二叉樹的存儲:二叉樹的存儲有兩種存儲方式,順序存儲和鏈式存儲。順序存儲是如圖所示:

極度的浪費空間,如果說空間中的空節點很多的話,會造成空間的極度浪費。

所以還有一種鏈式存儲,又叫二叉鏈表:

二叉樹節點的刪除:分3種情況

https://blog.csdn.net/isea533/article/details/80345507

二叉樹總體學習https://www.cnblogs.com/skywang12345/p/3576452.html

紅黑樹:紅黑樹的本質就是在節點信息上追加了一個表示顏色的信息而已

特點(不允許紅色節點和紅色節點相連,但是沒有說不允許黑色節點相連):

紅黑樹的自我修正(左旋,右旋,改變節點顏色),插入,刪除操作https://www.cnblogs.com/ysocean/p/8004211.html ,這篇文章中對於紅黑樹的刪除操作並沒有給出實際的分類情況,而是說刪除太復雜,是通過對刪除的節點做標記來完成刪除操作的。實際上刪除操作分為下面這幾種情況:

需要旋轉的4中情況的分析圖(規則有的時候是聯合使用):

 

例子:

 

下面正式開始學習 

Collecction(set,list:

Set(hashset,treeset:無序不重復,並不像list那樣擴充了許多新方法,所以無法使用l像ist集合中提供的get方法,所以無法實現指定索引數據的獲取。這是list和set的最大差別。

hashset:無序不重復,當添加重復的元素時,會無效。hashset判斷重復和treeset判斷重復不相同。利用的是object類中的方法進行比較。

首先會利用hashcode進行編碼的匹配,如果編碼不存在,說明不重復。如果編碼存在,那么這個時候進行進一步比較,如果發現重復了,則此數據則不運行保存。在java程序中實現真正的重復元素判斷用的是hashcode和equals兩個方法共同完成的。而只有在排序要求的情況下才會利用comparable接口完成。

treeset:當利用treeset保存的數據的時候所有的數據都按照數據的升序進行自動排序處理。但進行排序的類必須要實現comparable接口,因為只有實現了這個接口才可以比較對象的大小關系。treeset實際上是利用treemap子類實現的集合數據存儲,而treemap(樹)則需要根據comparable來確認大小關系。

注意在使用自定義類進行比較的時候,在繼承comparable后覆寫的方法之中一定要將該類中的所有屬性都依次比較,否則屬性相同的時候會以為是重復數據,所以可以得到得到treeset實際上是通過comparable來確認重復數據的。覆寫的方法如下:

但是如果類中的屬性過多,那么這將是一個很復雜的過程,所以在實際的開發中首選hashset子類。

List:

list和ArrayList:https://www.cnblogs.com/zcscnn/p/7743507.html

基本用法比較:https://blog.csdn.net/ftell/article/details/80826235

深入ArrayList:https://www.cnblogs.com/qingchunshiguang/p/6103731.html

Linkedlist和ArrayList對比:https://blog.csdn.net/weixin_41657730/article/details/82462156

Map(子類有hashmap,treemap,hashtable,linkedhashmap:對於map集合的數據保存格式就是按照“key=value”的形式存儲的,如果key重復,則會出現IllegalArgargumentException(如果是hashmap就會覆蓋)。如果說key為null,那么就是空指針異常。

HashMap(最常見):最常見的map

a.主要特點是無序,tree是有序。

b.在設置了相同的key的內容的時候put方法會返回原始的數據內容,如果沒有相同的key則返回null。

hashmap的原理https://baijiahao.baidu.com/s?id=1618550070727689060&wfr=spider&for=pc

面試題1:hashmap進行put操作的時候是如何進行容量擴充的?

a.首先會在hashmap中提供一個常量,作為初始化的容量配置,默認大小是16。

b.當保存的容量達到了一個閾值(默認是0.75),這里就是當保存了(16*0.75=12)個元素之后,就會進行容量的擴充。

c.在進行擴充的時候hashmap采用的是成倍的容量擴充,即每一次都擴充2倍(通過對老的容量向左移一位)。

面試題2:請解釋hashmap的工作原理(jdk1.8之后開始,hashmap在jdk1.8之后引入紅黑樹,因為大數據時代的來臨導致數據的爆棚,使得hashmap對數據量的存儲急劇增加,如果說還是使用原本的鏈表存儲大量的數據,會導致效率低下)

a.hashmap中的存儲依然是利用了node類完成,這種情況下的數據結構解釋鏈表和二叉樹(鏈表時間復雜度O(n),二叉樹時復雜度O(logn))。

b.從jdk1.8開始,hashmap的實現發生了改變,因為要適應大數據時代的到來,所以其存儲結構發生了變化,並且在hashmap的內部提供了重要的常量:

,在對hashmap進行數據保存的時候,如果保存的個數沒有超過閾值8,那么會按照鏈表的方式進行存儲,而如果超過了這個閾值,則會把鏈表轉化成紅黑樹以實現樹的平衡,並且利用左旋和右旋保證查找的性能。

面試題3:hashmap的容量為什么是2的n次方?

其中一個主要的方面就是通過hashcode和數組長度通過與運算來計算索引值。詳細見下

https://blog.csdn.net/j1231230/article/details/78072115

紅黑樹產生的問題:為什么使用了紅黑樹還說hashmap是無序的?

因為和treemap不同,treemap是直接將鍵值對中默認按照鍵的升序進行排序。而hashmap首先是按照鍵值轉化成的hashcode存儲在hashmap的數組中,當出現碰撞的時候才存儲在下面的鏈表中,如果說這個時候鏈表過長(超過8個)就會優化為紅黑樹,方便查找的時候更快,所以實際上紅黑樹在hashmap中的作用是為了解決碰撞過多導致的檢索慢的問題。實際在數組中還是無序的,數組查找時間復雜度是O(1)快於treemap,所以如果不用到排序的時候還是使用hashmap效率更高。

hashmap深入理解文章https://blog.csdn.net/visant/article/details/80045154

Linkedhashmap(有序的hashmap,屬於hashmap的子類,注意這里的有序指的是遍歷順序符合插入順序:https://www.jianshu.com/p/8f4f58b4b8ab

Hashtable(最早的一批動態數組實現類,很少使用了:hashtable在進行數據存儲的時候,如果key或者value為空都會出現空指針異常。

ConcurrentHashMap(hashtable的替代者,線程安全,分段):

jdk1.7下的concurrenthashmap

在jdk1.7和1.8的實現不相同,jdk7中采用的是分段的數組加鏈表實現,1.7中的存儲結構如下:

面試細節:https://www.cnblogs.com/heyonggang/p/9112731.html

jdk8下的concurrenthashmap(采用CAS + synchronized):

Java8中主要做了如下優化:
a.將Segment拋棄掉了,直接采用Node(繼承自Map.Entry)作為table元素。
b.修改時,不再采用ReentrantLock加鎖,直接用內置synchronized加鎖,java8的內置鎖比之前版本優化了很多,相較ReentrantLock,性能不並差。
c.size方法優化,增加了CounterCell內部類,用於並行計算每個bucket的元素數量。
jdk8中concurrenthashmap的數據結構:
jdk8中concurrenthashmap詳解: https://www.jianshu.com/p/85d158455861

面試題:請解釋hashmap的hashtable的區別?

hashmap中的方法屬於異步操作,非線程安全,hashmap允許保存有空數據。

hashtable中的方法都屬於同步方法,線程安全,hashtable不允許保存空數據,否則出現空指針異常。

TreeMap:底層通過紅黑樹實現

幾種map的對比:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM