1. 程式人生 > >Map 集合的回顧 與 java8 新增API的學習

Map 集合的回顧 與 java8 新增API的學習

簡述一下感想:

        本篇部落格重點是對Map 在 java8 版本新增的API的學習PS: 其實在java8版本對所有介面都進行了改寫,Map就是一個典例]

java 8 對Map介面的改寫重點就體現在.它在許多方法的引數中允許傳入一個函式式介面,對map中的資料進行邏輯處理;

重點: 本篇只介紹Map 介面的變化.不涉及Map介面派生的子介面;

重點: 本篇只介紹Map 介面的變化.不涉及Map介面派生的子介面;

重點: 本篇只介紹Map 介面的變化.不涉及Map介面派生的子介面;

重要的事情說3遍!!!!!!!!

Map的特點

1. map的特點

  1. map 儲存具有對映關係的資料
  2. map 儲存了兩組值
    1. key 無序不可重複 [set的特點][ps: map和set關係密切]
    2. value 無序可重複
  3. key 與 value 單向一一對應
    1. 只要找到key 就可以更具key按圖索驥找到對應的value;

2. map與set的相似之處

  1. Map裡的 key集與Set集合裡元素的儲存形式也很像;
  2. Map與Set的子類在名字上也驚人的相似
    1. Set
      1. HashSet
      2. LinkedHashSet
      3. SortedSet(介面)
      4. TreeSet
      5. EnumSet
      6. ..
    2. Map
      1. HashMap
      2. LinkedHashMap
      3. SortedMap(介面)
      4. TreeMap
      5. EnumMap
      6. ...

3. Map中常用的API方法;[其實無非就是增刪查改][推薦大家直接看程式碼塊]

  1. void clear(): 清空Map,刪除該Map物件中的所有Key-value
  2. boolean containsKey(Object key): 查詢map中是否包含某個key ,包含返回true,不包含返回false;
  3. Boolean containsValue(Object value) : 查詢map中是否包含該value .包含返回true,不包含返回false;
  4. Set entrySet(): 返回Map中包含的key-value 鍵值對做主組成的Set集合,每個集合元素都是Map.Entry(Entry 是 Map的內部類)物件
  5. Object get(Object key): 返回只對key所對應的Value;如果此Map中不包含該key.則返回null.
  6. Boolean isEmpty(): 查詢該Map是否為空(即不包含任何Key-value對),如果為空則返回true;
  7. Set keySet(): 返回該Map中所有key組成的Set集合.
  8. Object put(Object key,Object value): 新增一個key-value對,如果當前map中已存在該key.則value 覆蓋原來的value;
  9. void putAll(Map map) : 將制定Map中的key-value對複製到map中
  10. Object remove(Object key) : 刪除指定的key_value對,返回指定key的value;如果key不存在則返回null;
  11. int size(); 返回map鍵值對的個數
  12. Collection values(): 返回該map中value所組成的Collection.
  13. .... 詳見JDK api

4. map常見的3中遍歷方式[詳見下面附的程式碼塊----在最後最後最後]

  • keySet keySet集合
  • entryMap map內部類-
  • forEach() 方法 java 8 新增的

注意map 3 種遍歷的小小區別!!!

1. java8 為Map新增的方法[推薦大家直接看程式碼塊,程式碼塊中的註解有描述與情景]

  1. Object compute(Object key,BiFunction fm): 該方法使用 fm 根據原來的key-value計算一個新的value值
    1. 假如新的value 不為null 則替換掉舊的value;
    2. 假如新的value 和舊的的value 都為null ,則對本條鍵值對不做任何改變
    3. 假如舊的value 不為null 但是計算得出的新的value為null, 則刪除本條鍵值對
  2. Object computeIfAbsent(Object key,Function mf): 如果傳給該方法的key引數在Map中對應的value為null[前置條件],則使用mf 根據key計算一個新的value:
    1. 如果新的value不為null, 則覆蓋原來的value,如果為null也就沒變化,也沒意義;
    2. 如果map中不包含該Key 則會新增一組新的鍵值對;
  3. Object computeIfPresent(Object key,BiFunction rf) : 如果傳給該方法的key引數在Map中對應Value不為null[前置條件],則該方法使用rf根據原key,value計算一個新的value,
    1. 如果新的value不為null.則覆蓋原來value
    2. 如果新的value為null.則刪除該鍵值對
  4. void forEach(BiConsumer action); 該方法是java 8 為Map新增一個遍歷key-value對的方法.
  5. Object getOrDefault(Object key.V dValue) : 獲取指定key對應的value,如果該key不存在.則返回dValue;
  6. Object merge(Object key,Object value,BiFunction rf) : 該方法會先根據Key引數獲取該Map中對應的value,
    1. 如果獲取的value為null,則直接用傳入的value覆蓋原有的value(在這種情況下如果傳入的value也為null則刪除該key);
    2. 如果獲取的value不為null,則使用rf函式根據原value.新value計算一個新的結果,並用得到的結果去覆蓋原有的value;
  7. Object putIfAbsent(Object key,object value): 該方法會自動檢測指定的key對應的value是否為null,如果該key對應的value為null,該方法將會用新的value代替換來的null值;
  8. Object replace(Object key,Object value): 將Map中指定的key對應的value替換成新的value.與傳統的put()方法不同的是,該方法不可能新增新的key-value對.如果嘗試替換的key在原map中不存在.該方法不會新增key-value對,而是返回null.
  9. boolean replace(K key, V oldValue,V new Value) : 將Map中指定的key_value 對的源value替換成新value.如果在Map 中找到指定的key-value對.則執行替換並返回true,否則返回false.
  10. replaceAll(BiFunction f) 該方法使用BiFunction對原key-value 對進行計算,並將計算結果作為該key-value對的value值.

請copy下來跑一下...一切OK,看是沒有用的.跑跑.自己寫寫.測試一下

/**
 * map  回顧 與 java8 新增的API的學習
 */
public class MapTest {

    static Map<String, Object> map = new HashMap<>();

    /**
     * map 中的key 不可以重複; value可以重複
     */
    @Before
    public void before() {

        map.put("牛頓", 1000);
        map.put("愛因斯坦", 999);
        map.put("愛迪生", "電");
        map.put("特斯拉", "交流電");

    }

    @Test
    public void apiTest() {

        System.out.println("-----------apiTest Start---------------");
        System.out.println();
        /*
        假如放入對某個key進行覆蓋.會返回原本的key
         */
        Object o = map.put("愛迪生", "發明電燈泡");
        System.out.println(Objects.toString(o));

        System.out.println();
        System.out.println("--------------美麗的分割線-----------");
        System.out.println("是否包含某個key.包含返回true,反之false  :  " + map.containsKey("愛迪生"));
        System.out.println("是否包含某個value.包含返回true,反之false:  " + map.containsValue("愛迪生"));

        System.out.println();
        System.out.println("--------------美麗的分割線-----------");
        System.out.println("根據指定key,返回對應的value.如果不存在該key,返回null:  " + map.get("adb"));
        System.out.println("根據指定key,返回對應的value.如果不存在該key,返回null:  " + map.get("愛迪生"));

        System.out.println();
        System.out.println("--------------美麗的分割線-----------");
        System.out.println("判斷map是否為空:   " + map.isEmpty());

        /*
        putAll 的前提是 泛型一致,否則編譯出錯
         */
        HashMap<String, Object> mmap = new HashMap<>();
        mmap.put("998", "只要998 買不了吃虧買不了上當");
        mmap.put("111", "110 120 119");

        System.out.println();
        System.out.println("--------------美麗的分割線-----------");
        System.out.println("原始map key_value 對數 : " + map.size());
        map.putAll(mmap);
        System.out.println("putAll後 key_value 對數 : " + map.size());

        System.out.println();
        System.out.println("--------------美麗的分割線-----------");
        System.out.println(" ---------remove 返回的性質類似於get ---------");
        System.out.println("remove 刪除指定key的value 如果key不存在 返回null : " + map.remove("111"));
        System.out.println("remove 刪除指定key的value 如果key不存在 返回null : " + map.remove("9999"));

        System.out.println();
        System.out.println("--------------美麗的分割線-----------");
        System.out.println(" remove key_value 對 成功 true, 反之 false :  " + map.remove("111", 999));

        System.out.println();
        System.out.println("-----------apiTest End---------------");

    }

    /**
     *
     */
    @Test
    public void java8ApiTest() {
        /*
        Object compute(Object key,BiFunction fm): 該方法使用 fm 根據原來的key-value計算一個新的value值
        假如新的value 不為null 則替換掉舊的value;
        假如新的value 和舊的的value 都為null ,則對本條鍵值對不做任何改變,其實改變也沒有任何意義,反正都一樣
        假如舊的value 不為null 但是計算得出的新的value為null, 則刪除本條鍵值對
         */
        System.out.println();
        System.out.println("--------------------------------------");
        System.out.println("compute:");
        System.out.println("--------------------------------------");
        System.out.println(" 假如新的value 不為null 則替換掉舊的value: ");
        Object o = map.compute("愛迪生", (key, value) -> key + value);
        System.out.println(Objects.toString(o));
        System.out.println(map.get("愛迪生"));
        System.out.println(" 假如舊的value 不為null 但是計算得出的新的value為null, 則刪除本條鍵值對: ");
        Object a = map.compute("愛迪生", (key, value) -> null);
        System.out.println(map.get("愛迪生"));


        /*
        Object computeIfAbsent(Object key,Function mf): 如果傳給該方法的key引數在Map中對應的value為null,
        則使用mf 根據key計算一個新的value:
            如果新的value不為null, 則覆蓋原來的value
            如果map中不包含該Key 則會新增一組新的鍵值對;
         */
        System.out.println();
        System.out.println("--------------------------------------");
        System.out.println("computeIfAbsent:");
        System.out.println("--------------------------------------");
        System.out.println("如果map中不包含該Key 則會新增一組新的鍵值對;");
        map.computeIfAbsent("愛迪生", key -> key.length()
        );
        System.out.println(map.get("愛迪生"));
        //前提是傳給該方法的key引數的value為null
        map.put("aaa", null);
        System.out.println("如果新的value不為null, 則覆蓋原來的value");
        map.computeIfAbsent("aaa", key -> (key.length() + key)
        );
        System.out.println(map.get("aaa"));


        /*
         Object computeIfPresent(Object key,BiFunction rf) :
         如果傳給該方法的key引數在Map中對應Value不為null,
         則該方法使用rf根據原key,value計算一個新的value,
                如果新的value不為null.則覆蓋原來value
                如果新的value為null.則刪除該鍵值對

            前提是傳入key的value不為null
         */
        System.out.println();
        System.out.println("--------------------------------------");
        System.out.println("computeIfPresent:  ");
        System.out.println("--------------------------------------");
        System.out.println("如果新的value不為null.則覆蓋原來value");
        Object aaa = map.computeIfPresent("aaa", (key, value) -> {
            return key.length() + ((String) value).length() + "";
        });
        System.out.println(map);

        System.out.println("如果新的value為null.則刪除該鍵值對");
        map.computeIfPresent("aaa", (key, value) -> {
            return null;
        });
        System.out.println(map);

        /*
        Object getOrDefault(Object key,V dValue) : 獲取指定key對應的value,如果該key不存在.則返回DValue;
         */
        System.out.println();
        System.out.println("--------------------------------------");
        System.out.println("getOrDefault:");
        System.out.println("--------------------------------------");
        Object ads = map.getOrDefault("愛迪生", 998);
        System.out.println(ads);


        /*
        Object merge(Object key,Object value,BiFunction rf) :
         該方法會先根據Key引數獲取該Map中對應的value,
            如果key對應的value為null,
                則直接用傳入的value覆蓋原有的value
                    (在這種情況下如果傳入的value也為null則刪除該key);
            如果key對應的value不為null,
                則使用rf函式根據原value與
                    新value計算一個新的結果,並用得到的結果去覆蓋原有的value;
         */
        System.out.println();
        System.out.println("--------------------------------------");
        System.out.println("merge:");
        System.out.println("--------------------------------------");
        map.put("勞力士", null);
        map.merge("勞力士", "998", (oldValue, newValue) -> {
            return oldValue + "" + newValue;
        });
        System.out.println(map);

        /*
        注意雖然,方法沒有要求 value的值不可以傳入null,如果傳入了null就會丟擲空指標異常
        檢視原始碼.merge 預設方法 中第一步就是對傳入的引數進行非空校驗.
        --
            以下為原始碼片段
                Objects.requireNonNull(remappingFunction);
                Objects.requireNonNull(value);
            值得一提的是key 可以傳入null
         */
//        map.merge("勞力士",null,(oldValue,newValue)->{
//            return oldValue+""+newValue;
//        });
//        System.out.println(map);
        map.merge("勞力士", "998", (oldValue, newValue) -> {
            return null;
        });
        System.out.println(map);
        map.merge("愛因斯坦", "998", (oldValue, newValue) -> {
            return oldValue + "" + newValue;
        });
        System.out.println(map);
    }


    @Test
    public void java8ApiTest2() {

        /*
           Object putIfAbsent(Object key,object value):
               該方法會自動檢測指定的key對應的value是否為null,
                    如果該key對應的value為null,
                    該方法將會用新的value代替換來的null值;
         */
        //情景1:  假如 key 不存在. 它就和put方法沒有區別
        //情景2: 假如key存在.就會自動檢測key對應的value是否為null,如果為null,則用引數中的value替代,反之沒變化
        System.out.println(map);
        map.putIfAbsent("name", null);
        System.out.println(map);
        map.putIfAbsent("name", "詹姆斯.高斯林");
        System.out.println(map);
        map.putIfAbsent("name", "name is flag");
        System.out.println(map);

        /*
           Object replace(Object key,Object value):
               將Map中指定的key對應的value替換成新的value.
               與傳統的put()方法不同的是,該方法不可能新增新的key-value對.
               如果嘗試替換的key在原map中不存在.該方法不會新增key-value對,而是返回null.
         */
        // 前提是key值存在.然後新value替換舊value
        // 假如 key不存在.不好意思.返回null map無變化sout
        System.out.println();
        System.out.println("----------------------------");
        System.out.println("---------replace------------");
        System.out.println("----------------------------");

        map.replace("name", "妹大爺");
        System.out.println(map);
        map.replace("abc", "字元"); // key不存在, map無變化
        System.out.println(map);


        /*
        boolean replace(K key, V oldValue,V new Value) :
             將Map中指定的key_value 對的源value替換成新value.
             如果在Map 中找到指定的key-value對.
             則執行替換並返回true,否則返回false.
         */
        System.out.println();
        System.out.println("----------------------------");
        System.out.println("---------replace2------------");
        System.out.println("----------------------------");
        System.out.println(map);
        // 情景1: 假如key-value對存在.則新的value替換舊的value,並返回true
        System.out.println(map.replace("name", "妹大爺", "梅蘭芳"));
        System.out.println(map);
        // 情景2: 假如 key-value對不存在,則map不會發生變化,並返回false
        System.out.println(map.replace("name", "你大爺", "你二大爺"));
        System.out.println(map);

        /*
         replaceAll(BiFunction f)
             該方法使用BiFunction對原key-value對進行計算,
             並將計算結果作為該key-value對的value值.
         */
        System.out.println();
        System.out.println("----------------------------");
        System.out.println("---------replaceAll------------");
        System.out.println("----------------------------");
        System.out.println(map);
        map.replaceAll((k, v) -> {
            return k + "-" + v;
        });
        System.out.println(map);

    }

     /**
     * map 的3中遍歷方式
     *    有小小的區別
     */
    @Test
    public void mapTest() {

        Map<String, Object> map = new HashMap<>();
        map.put("西遊記", 112);
        map.put("水滸傳", 993);
        map.put("紅樓夢", 322);
        map.put("三國演義", 998);
        System.out.println("--------------------map的原始遍歷方式 1-----------------------");
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            if("西遊記".equals(key)){
                map.put("西遊記","吳承恩");
            }
            System.out.println(key + " :  " + map.get(key));
        }
        System.out.println("--------------------map的原始遍歷方式 2-----------------------");
        Set<Map.Entry<String, Object>> entries = map.entrySet();
        for (Map.Entry<String, Object> mp : entries) {
            String key   = mp.getKey();
            Object value = mp.getValue();
            if("西遊記".equals(key)){
                map.put("西遊記",998998989);
            }
            System.out.println(key + " :  " + value);
        }

        System.out.println("--------------------map的Lamdba遍歷方式 3-----------------------");
        map.forEach((key, value) -> {
            if("西遊記".equals(key)){
                map.put("西遊記","吳承恩");
            }
            System.out.println(key + " :  " + value);
        });

        /*
            值得一提的java8 提供的forEach方法 操作的map集合,其實是取出entry物件在操作,也就是所有的key-value...
            所以在修改過後再去遍歷.還是原來的entry[key-value]
         */
        System.out.println("--------------------------再遍歷一次map--------------------------------");
        map.forEach((key,value) ->{
            System.out.println(key + " :  " + value);
        });
    }
}