1. 程式人生 > 實用技巧 >雙列集合框架:Map

雙列集合框架:Map

1.常用實現類結構
|----Map:雙列資料,儲存key-value對的資料 ---類似於高中的函式:y = f(x)
  * |----HashMap:作為Map的主要實現類;執行緒不安全的,效率高;儲存null的key和value
    * |----LinkedHashMap:保證在遍歷map元素時,可以照新增的順序實現遍歷。
      * 原因:在原的HashMap底層結構基礎上,添加了一對指標,指向前一個和後一個元素。
      * 對於頻繁的遍歷操作,此類執行效率高於HashMap。


  * |----TreeMap:保證照新增的key-value對進行排序,實現排序遍歷。此時考慮key的自然排序或定製排序
         * 底層使用紅黑樹
  * |----Hashtable:作為古老的實現類;執行緒安全的,效率低;不能儲存null的key和value
    * |----Properties:常用來處理配置檔案。key和value都是String型別
*
*
* HashMap的底層:陣列+連結串列 (jdk7及之前)
* 陣列+連結串列+紅黑樹 (jdk 8)

2.儲存結構的理解
>Map中的key:無序的、不可重複的,使用Set儲存所的key ---> key所在的類要重寫equals()和hashCode() (以HashMap為例)
>Map中的value:無序的、可重複的,使用Collection儲存所的value --->value所在的類要重寫equals()
> 一個鍵值對:key-value構成了一個Entry物件。
>Map中的entry:無序的、不可重複的,使用Set儲存所的entry

3.常用方法
* 新增:put(Object key,Object value)
* 刪除:remove(Object key)


* 修改:put(Object key,Object value)
* 查詢:get(Object key)
* 長度:size()
* 遍歷:keySet() / values() / entrySet()

public class MapTest {
    public static void main(String[] args) {
        HashMap hash = new HashMap();
        hash.put("aa",123);
        hash.put("bb",54);
        hash.put("uu","h");
        hash.put("pp",21);

        Set set = hash.keySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println("*******");
        Collection values = hash.values();
        for(Object obj: values){
            System.out.println(obj);
        }



        System.out.println("*******");
        Set set1 = hash.entrySet();
        Iterator iterator1 = set1.iterator();
        while (iterator1.hasNext()){
            System.out.println(iterator1.next());
        }
    }
}

4. 記憶體結構說明:(難點)
4.1 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(key2)方法,比較:
* 如果equals()返回false:此時key1-value1新增成功。----情況3
* 如果equals()返回true:使用value1替換value2。
*
* 補充:關於情況2和情況3:此時key1-value1和原來的資料以連結串列的方式儲存。
*
* 在不斷的新增過程中,會涉及到擴容問題,當超出臨界值(且要存放的位置非空)時,擴容。預設的擴容方式:擴容為原來容量的2倍,並將原的資料複製過來。

4.2 HashMap在jdk8中相較於jdk7在底層實現方面的不同:
1. new HashMap():底層沒建立一個長度為16的陣列
2. jdk 8底層的陣列是:Node[],而非Entry[]
3. 首次呼叫put()方法時,底層建立長度為16的陣列
4. jdk7底層結構只:陣列+連結串列。jdk8中底層結構:陣列+連結串列+紅黑樹。
4.1 形成連結串列時,七上八下(jdk7:新的元素指向舊的元素。jdk8:舊的元素指向新的元素)
4.2 當陣列的某一個索引位置上的元素以連結串列形式存在的資料個數 > 8 且當前陣列的長度 > 64時,此時此索引位置上的所資料改為使用紅黑樹儲存。

4.3 HashMap底層典型屬性的屬性的說明
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

4.4 LinkedHashMap的底層實現原理(瞭解)
LinkedHashMap底層使用的結構與HashMap相同,因為LinkedHashMap繼承於HashMap.
區別就在於:LinkedHashMap內部提供了Entry,替換HashMap中的Node.

5. TreeMap的使用
//向TreeMap中新增key-value,要求key必須是由同一個類建立的物件
//因為要照key進行排序:自然排序 、定製排序

6.使用Properties讀取配置檔案

//Properties:常用來處理配置檔案。key和value都是String型別
public static void main(String[] args)  {
    FileInputStream fis = null;
    try {
        Properties pros = new Properties();

        fis = new FileInputStream("jdbc.properties");
        pros.load(fis);//載入流對應的檔案

        String name = pros.getProperty("name");
        String password = pros.getProperty("password");

        System.out.println("name = " + name + ", password = " + password);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(fis != null){
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

配置檔案jdbc.properties

name=education
password=12345