Map介面

  • 2021 年 12 月 23 日
  • 筆記
/**
* 一、Map的實現類的結構:
* /----Map:雙列數據,用於存儲key-value對的數據 ---類似於函數:y = f(x)
* /----HashMap:作為Map的主要實現類;執行緒不安全的,效率高;可存儲null的key-value
* /----LinkedHashMap:保證在遍歷map元素時,可以按照添加的順序實現遍歷。
* 原因:在原有的HashMap底層結構基礎上添加了一對指針,指向前一個和後一個元素
* 對於頻繁的添加操作,此類執行效率高於HashMap
* /----TreeMap:保證按照添加的key-value對進行排序,實現排序遍歷。此時考慮key的自然排序或訂製排序
* 底層使用紅黑樹
* /----Hashtable(注意t是小寫):作為古老的實現類;執行緒安全的,效率低;不能存儲null的key-value
* /----Properties:常用來處理配置文件。key和value都是String類型
*
* HashMap的底層:數組+鏈表 (jdk7之前)
* 數組+鏈表+紅黑樹 (jdk8)
*面試題:
* 1.HashMap的底層實現原理?
* 2.HashMap和Hashtable的異同?
* 3.CurrentHashMap與Hashtable的異同?
*
* 二、Map結構的理解
* Map中的key:無序的、不可重複的,使用Set去存儲所有的key---->key所在類要重寫equals()和hashCode() (以HashMap為例)
* Map中的value:無序的,可重複的,使用Collection存儲所有的value---->value所在類要重寫equals(),
* 一個鍵值對:key-value構成了一個Entry對象。
* Map中的entry:無序、不可重複的,使用Set存儲所有的entry
*
* 三、HashMap的底層實現原理?以jdk7為例說明:
* HashMap map = new HashMap():
* 在實例化以後,底層創建了長度是16的一維數組 Entry[] table
* ....可能已經執行過多次put....
* map.put(key1,value1):
* 首先,調用key1所在類的hashCode()計算key1的哈希值,此哈希值經過某種演算法計算以後,得到在Entry數組的存放位置
* 如果此位置上的數據為空,此時的key1-value1添加成功。---->情況1
* 如果此位置上的數據不為空(意味著此位置上存在一個或多個數據(以鏈表形式存在)),比較key1和已經存在的一個或多個數據的哈希值:
* 如果key1的哈希值與已經存在的數據的哈希值都不相同,此時key1-value1添加成功。---->情況2
* 如果key1的哈希值與已經存在的某一個數據(key2-value2)的哈希值相同:繼續比較:調用key1所在類的equals()方法:
* 如果equals返回false:此時key1-value1添加成功---->情況3
* 如果equals返回true:使用value1替換value2
*
* 補充:關於情況2和情況3:此時key1-value1和原來的數據以鏈表的方式存儲。
*
* 在不斷的添加過程中,會設計到擴容問題:當超出臨界值(且要存放的位置非空)時,擴容為原來容量的2倍,並將原有的數據複製過來。
*
* jak8相較於jdk7在底層實現方面的不同:
* 1.new HashMap():底層沒有創建一個長度為16的Entry數組
* 2.jdk8 底層的數組是Node[],而非Entry[]
* 3.首次調用put()時,底層創建長度為16的數組
* 4.原來jdk7底層結構只有:數組+鏈表,jdk8 中底層結構:數組+鏈表+紅黑樹。
* 當數組的某一個索引位置上的元素以鏈表存在的數據個數 > 8 且當前數組的長度超過 > 64時,
* 此時此索引位置上的所有數據改為使用紅黑樹存儲
*
* DEFAULT_INITIAL_CAPACITY :HashMap的默認容量 16
* DEFAULT_LOAD_FACTOR :HashMap的默認載入因子 0.75
* threshold:擴容的臨界值:= 容量*載入因子 :16*0.75 =12
* TREEIFY_THRESHOLD: Bucket中鏈表長度大於該默認值,轉化為紅黑樹:8
* MIN_TREEIFY_CAPACITY : 桶中的Node被樹化時最小的hash表容量:64
*
* 四、LinkedHashMap的底層實現原理(了解)
* 源碼中:
* static class Entry<K,V> extends HashMap.Node<K,V> {
* Entry<K,V> before, after;//能夠記錄添加的元素的先後順序
* Entry(int hash, K key, V value, Node<K,V> next) {
* super(hash, key, value, next);
* }
* }
*


Tags: