hashMap常見問題

解析hashMap的源碼實現】   

     點擊進入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已經實現。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章