package com.study.java; import org.junit.jupiter.api.Test; import java.util.HashMap; /** * /----Map:雙列數據 存儲key-value對的數據 * /----HashMap:做爲Map的主要實現類;線程不安全,效率高,存儲null的key和value * /----LinkedHashMap:保證遍歷map元素時,能夠按添加順序實現遍歷 * 緣由:在原有的HashMap底層結構基礎上,添加了一對指針,指向前一個和後一個元素。 * /----TreeMap:保證按照添加的key-value對進行排序,實現排序遍歷。此時考慮key的天然排序或訂製排序 * 底層使用紅黑樹 * /----Hashtable:做爲古老的實現類,線程安全,效率低;不能存儲null的key和value * /----Properties:經常使用來處理配置文件。key和value都是string類型 * * * HashMap底層:數組+鏈表 (jdk7及之前) * 數組+鏈表+紅黑樹 (jdk8) * * Map結構的理解: * Map中的key:無序的、不可重複的,使用Set存儲全部的key key所在的類要重寫equals和hashCode方法 * Map中的value:無序的,可重複,使用Collection存儲全部的value value所在類要重寫equals方法 * 一個鍵值對:key-value構成一個Entry對象 * Map中的Entry:無序的、不可重複的,使用Set存儲全部的entry * * * HashMap的底層實現原理,jdk7爲例: * HashMap map = new HashMap(); * 在實例化後,底層建立了長度爲16的一維數組Entry[]table * ...... * map.put(k1, v1) * 首先,調用k1所在類的hashcode()計算k1的哈希值,此哈希值通過某種算法計算後,獲得Entry數組存放的位置 * 若是此位置上數據爲空,此時K1-v1添加成功 * 若是此位置上的數據不爲空,(意味着此位置上存放一個或多個數據(以鏈表形式存在)),比較k1和已經存在的一個或多個數據的哈希值:4 * 若是k1的哈希值和已經存在的數據哈希值都不相同,此時K1-v1添加成功。 狀況1 * 若是k1的哈希值和已經存在的某一個數據(k2-v2)的哈希值相同,繼續比較:調用k1所在類的equals(k2)方法,比較: * 若是equals返回false :添加成功 狀況2 * 若是equals返回true:將v1替換相同key的value值 * 補充:關於狀況2和狀況3,此時key1-value1和原來的數據以鏈表的形式存儲 * 在不斷添加過程,會涉及擴容問題,默認擴容方式:擴容爲原來容量的兩倍,並將原有的數據複製過來 * * jdk8相較於jdk7在底層實現方面的不一樣: * 1. new HashMap():底層沒有建立一個長度爲16的數組 * 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表容量 * * * LinkedHashMap的底層實現原理:,添加數據時,還維護了兩個引用,記錄前一個和後一個數據 * * TreeMap 中添加key-value,要求key必須是由同一個類建立的對象 * //由於要按照key進行排序:天然排序、訂製排序 * * Properties:經常使用來處理配置文件。key和value都是string類型 */ public class MapTest { @Test public void test1() { HashMap hashMap = new HashMap(); hashMap.put(null, 123); hashMap.put(222, "aa"); hashMap.put(223, "bb"); System.out.println(hashMap); } @Test public void test2() { HashMap hashMap = new HashMap(); hashMap.put(null, 123); hashMap.put(222, "aa"); hashMap.put(223, "bb"); System.out.println(hashMap); } }