【解析hashMap的源碼實現】
0、談談對hashMap的理解?
從底層結構、存取、擴容、衝突、實現原理、源碼等方面說明。
1、你知道哪些常用的Map集合?
HashMap、HashTable、LinkedHashMap、ConcurrentHashMap。
2、Collection集合接口和Map接口有什麼關係?
List,Set都是繼承自Collection接口(單列集合),Map則不是(雙列集合)。
3、HashMap是線程安全的嗎?線程安全的Map都有哪些?性能最好的是哪個?
HashMap不是線程安全的。
線程安全的有HashTable、ConcurrentHashMap、SynchronizedMap。
性能最好的是ConcurrentHashMap。
4、使用HashMap有什麼性能問題嗎?
使用HashMap要注意避免集合的擴容。
它會很耗性能(擴容後要進行索引重排),根據元素的數量給它一個初始大小的值。
5、HashMap的數據結構是怎樣的?默認大小是多少?內部是怎麼擴容的?
HashMap是數組和鏈表組成的。
默認大小爲16。
當hashmap中的元素個數超過數組大小*loadFactor(默認值爲0.75)時就會把數組的大小擴展爲原來的兩倍大小,然後重新計算每個元素在數組中的位置。
5.1爲什麼擴容是原先的兩倍?【***】
連接:hashMap的擴容機制resize()
使用一個容量更大的數組來代替已有的容量小的數組,transfer()方法將原有Entry數組的元素拷貝到新的Entry數組裏。
6、怎麼按添加順序存儲元素?怎麼按A-Z自然順序存儲元素?怎麼自定義排序?
按添加順序使用LinkedHashMap。
按自然順序使用TreeMap。
按自定義排序TreeMap(Comparetor c)。
7、HashMap的鏈表結構設計是用來解決什麼問題的?
HashMap的鏈表結構設計是用來解決key的hash衝突問題的。
8、HashMap的鍵、值可以爲NULL嗎?HashTable呢?
HashMap的鍵值都可以爲NULL,HashTable不行。
9、HashMap使用對象作爲key,如果hashcode相同會怎麼處理?
key的hash衝突,如果key equals一致將會覆蓋值,不一致就會將值存儲在key對應的鏈表中。
10、HashMap中的get操作是什麼原理?
先根據key的hashcode值找到對應的鏈表,再循環鏈表,equals比較操作找到對應的值。
11、hashCode相等的兩個類一定相等嗎?equals呢?相反呢?
hashCoded相等的兩個類不一定相等,equals相等了一定相等。
12、介紹一下集合框架?單列集合、雙列結合
* Collection 一次存一個對象, 單列集合
* List 可重複, 有索引,存取有序
1、ArrayList 數組實現, 查找快,增刪慢
查找快是因爲有索引,增刪滿是因爲增刪後需要進行索引重排。
2、LinkedList 鏈表實現, 增刪快
增刪快是因爲需要進行索引重排,只需要改變鏈表元素前後的引用即可。
3、Vector 數組實現, 線程安全
線程安全是因爲增刪操作使用了synchronize同步鎖。
* Set 不可重複, 沒索引,存取無序
1、HashSet 使用哈希算法去重複, 效率高, 但元素無序
2、TreeSet 使用二叉樹算法排序, 可以指定元素的存儲順序
3、LinkedHashSet HashSet的子類, 原理相同, 除了去重複之外還能保留存儲順序
* Map 一次存兩個對象, 鍵值對
1、HashMap 使用哈希算法對鍵去重複, 效率高, 但無序
2、TreeMap 使用二叉樹算法排序, 可以自定義順序
3、LinkedHashMap 使用哈希算法去重複, 並且保留存儲順序
4、Hashtable 類似HashMap, 線程安全, 效率略低, 不允許null鍵和null值
5、SynchronizedHashMap
6、ConcurrentHashMap 是併發包下線程安全的hashmap
在JDK1.8以前ConcurrentHashMap 使用了分段加鎖(原理)的方式保證了高效率的線程安全,JDK1.8及以後使用了紅黑樹和CAS算法保證ConcurrentHashMap 的線程安全。
13、hashMap、hashTable、concurrentHashMap底層實現?
hashMap:
鏈表和數組的結合體
hashTable:
散列結構和hashmap一樣
concurrentHashMap:
14、hashMap和treeMap的區別?底層用到什麼數據結構?
1、實現 (底層數據結構)
TreeMap:SortMap接口,基於紅黑樹
HashMap:基於哈希散列表實現
2、存儲
TreeMap:默認按鍵的升序排序
HashMap:隨機存儲
3、遍歷
TreeMap:Iterator遍歷是排序的
HashMap:Iterator遍歷是隨機的
4、性能損耗
TreeMap:插入、刪除
HashMap:基本無
5、鍵值對
TreeMap:鍵、值都不能爲null
HashMap:只允許鍵、值均爲null
6、安全
TreeMap:非併發安全Map
HashMap:非併發安全Map
7、效率
TreeMap:低
HashMap:高
* 一般情況下我們選用HashMap,因爲HashMap的鍵值對在取出時是隨機的,其依據鍵的hashCode和鍵的equals方法存取數據,具有很快的訪問速度,所以在Map中插入、刪除及索引元素時其是效率最高的實現。而TreeMap的鍵值對在取出時是排過序的,所以效率會低點。
15、線程安全與線程不安全的集合?
* 線程安全:
StringBuffer、HashTable、Vector、SynchronizedHashMap、concurrentHashMap
* 線程不安全:
StringBuilder、HashMap、LinkedList、ArrayList、HashSet
16、hashMap的原理,底層數據結構?*****
底層使用 哈希表(數組+鏈表)的數據結構,當鏈表過長,會將鏈表轉成紅黑樹以實現O(logn)時間複雜度查詢。
17、講一講hashMap中put方法的過程?*****
1、對key求hash值,計算下標
2、如果沒有碰撞直接放入桶中
3、如果碰撞了以鏈表的方式,連接到後邊
4、如果鏈表長度超過閾值(TREEIFY_THRESHOLD == 8)就把鏈表轉成紅黑樹。
5、如果節點已經存在就替換舊值。
6、如果桶滿了(容量*加載因子)就需要resize()擴容爲原來的2倍。
18、hashMap中的hash函數是怎麼實現的?還有哪些hash的實現方式?*****
1、高16bit不變,高16bit和低16bit做了一個異或。
2、(n-1)& hash得到下標
還有哪些hash實現方式,可以參考Effective Java 學習筆記 hashCode()
19、hashMap是怎麼解決hash衝突的,講一下擴容過程,加入一個值在原數組中,現在移動了新數組,位置肯定變了,那是什麼定位到了這個值在數據中的位置?*****
1、將新節點加到鏈表後
2、容量擴充爲原來的兩倍,然後對每個節點重新計算hash值。
3、這個值只可能存在兩個地方,一個是原下標的位置,另一種是在下標爲<原下標 + 原容量的位置>。
20、拋開hashMap,hash衝突有哪些解決辦法?
開放定址、鏈地址法。
21、針對hashMap中某個Entrty鏈太長,查找的時間複雜度可能達到O(n)怎麼優化?
鏈表轉爲紅黑樹,JKD 1.8已經實現。