【集合類】源碼解析之 Map接口

Map接口

雙列集合,鍵值對(確保鍵的唯一)

構造函數

public interface Map<K,V>

內部接口 Entry

抽象了內部存儲的節點,對應一個鍵值對

interface Entry<K,V> {
	// 返回此項的Key
    K getKey();

	// 返回此項的value
    V getValue();

	// 設置此項的value
    V setValue(V value);

    /**
     * 兩個entry比較相等性
     *  (e1.getKey() == null ? e2.getKey() == null : e1.getKey().equals(e2.getKey())) &&
     *  (e1.getValue() == null ? e2.getValue() == null : e1.getValue().equals(e2.getValue()))
     */
    boolean equals(Object o);

	/**
     *  (e.getKey() == null ? 0 : e.getKey().hashCode()) ^
     *  (e.getValue() == null ? 0 : e.getValue().hashCode())
     */
    int hashCode();

	// 返回一個比較器 ,按鍵自然順序比較Map.Entry 
    public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {
        return (Comparator<Map.Entry<K, V>> & Serializable)
            (c1, c2) -> c1.getKey().compareTo(c2.getKey());
    }

	// 返回一個比較器,比較Map.Entry的自然順序值
    public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
        return (Comparator<Map.Entry<K, V>> & Serializable)
            (c1, c2) -> c1.getValue().compareTo(c2.getValue());
    }

	// 返回一個比較器,比較Map.Entry按鍵使用給定的Comparator 
    public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
        Objects.requireNonNull(cmp);
        return (Comparator<Map.Entry<K, V>> & Serializable)
            (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
    }

	// 返回一個比較器 ,使用給定的Comparator比較Map.Entry的值
    public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
        Objects.requireNonNull(cmp);
        return (Comparator<Map.Entry<K, V>> & Serializable)
            (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
    }
}

這裏有出現個之前沒見過的寫法 (Comparator<Map.Entry<K, V>> & Serializable)& 我們知道是按位與的操作,那麼兩個對象之間使用呢?

對象強轉爲Comparator的同時也支持序列化

其實這個是java語法支持的強制類型轉換表達式 ( ReferenceType & InterfaceType ) LambdaExpression,也就是說Lambda表達式被轉化爲引用類型和接口類型兩種類型

共性方法

// 返回鍵值對的數目,如果大於Integer.MAX_VALUE,則返回Integer.MAX_VALUE
int size();

// 如果map不包含鍵值對則返true
boolean isEmpty();

// 判斷是否包含Key 
boolean containsKey(Object key);

// 判斷是否包含value
boolean containsValue(Object value);

// 返回到指定鍵所映射的值,如果不存在返回null(也可能是value就是null值)
V get(Object key);

// 將key和value進行關聯,如果已存在key,則value將替換舊值並返回舊值,如果不存在key則返回null(也可能舊值就是null值)
V put(K key, V value);

// 如果key存在,則刪除該key的映射,並返回value值,如果不存在返回null(也可能是value就是null值)
V remove(Object key);

// 將指定map中的鍵值對賦值到此map中
void putAll(Map<? extends K, ? extends V> m);

// 刪除所有鍵值對
void clear();

// map的三視圖之一,key的Set視圖
Set<K> keySet();

// map的三視圖之一,value的Collection視圖
Collection<V> values();

// map的三視圖之一,entry的Set視圖
Set<Map.Entry<K, V>> entrySet();

jdk1.8新增的默認方法

// 獲取指定key對應的value,如果指定key不存在則返回指定的默認vaule
default V getOrDefault(Object key, V defaultValue) {
    V v;
    return (((v = get(key)) != null) || containsKey(key)) ? v : defaultValue;
}

// foreach循環
default void forEach(BiConsumer<? super K, ? super V> action) {
    Objects.requireNonNull(action);
    for (Map.Entry<K, V> entry : entrySet()) {
        K k;
        V v;
        try {
            k = entry.getKey();
            v = entry.getValue();
        } catch(IllegalStateException ise) {
            // this usually means the entry is no longer in the map.
            throw new ConcurrentModificationException(ise);
        }
        action.accept(k, v);
    }
}

// 將指定函數作用在所有key的value上
default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
    Objects.requireNonNull(function);
    for (Map.Entry<K, V> entry : entrySet()) {
        K k;
        V v;
        try {
            k = entry.getKey();
            v = entry.getValue();
        } catch(IllegalStateException ise) {
            throw new ConcurrentModificationException(ise);
        }
        v = function.apply(k, v);

        try {
            entry.setValue(v);
        } catch(IllegalStateException ise) {
            throw new ConcurrentModificationException(ise);
        }
    }
}

// 如果key存在並且對應的value並不爲null則直接返回value,否則執行put操作
default V putIfAbsent(K key, V value) {
    V v = get(key);
    if (v == null) {
        v = put(key, value);
    }

    return v;
}

// 根據key-value匹配刪除,只有在key存在並且值相同時才執行remove操作
default boolean remove(Object key, Object value) {
    Object curValue = get(key);
    if (!Objects.equals(curValue, value) ||
        (curValue == null && !containsKey(key))) {
        return false;
    }
    remove(key);
    return true;
}

// 根據key-value匹配再替換舊值,只有key存在並且值相同時,才執行put操作
default boolean replace(K key, V oldValue, V newValue) {
    Object curValue = get(key);
    if (!Objects.equals(curValue, oldValue) ||
        (curValue == null && !containsKey(key))) {
        return false;
    }
    put(key, newValue);
    return true;
}

// 只有根據key匹配到了具體的鍵值對,才執行put操作並且返回舊值
default V replace(K key, V value) {
    V curValue;
    if (((curValue = get(key)) != null) || containsKey(key)) {
        curValue = put(key, value);
    }
    return curValue;
}

// 根據key獲取value,如果key不存在或者存在但是映射的value爲null,則根據指定函數執行put操作返回新值
default V computeIfAbsent(K key,
                          Function<? super K, ? extends V> mappingFunction) {
    Objects.requireNonNull(mappingFunction);
    V v;
    if ((v = get(key)) == null) {
        V newValue;
        if ((newValue = mappingFunction.apply(key)) != null) {
            put(key, newValue);
            return newValue;
        }
    }

    return v;
}

// 只要key存在,並且對應的value不爲null,則根據指定函數執行put操作返回新值,否則返回null。
// 如果指定函數返回值爲null,則代表刪除該key
default V computeIfPresent(K key,
                           BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
    Objects.requireNonNull(remappingFunction);
    V oldValue;
    if ((oldValue = get(key)) != null) {
        V newValue = remappingFunction.apply(key, oldValue);
        if (newValue != null) {
            put(key, newValue);
            return newValue;
        } else {
            remove(key);
            return null;
        }
    } else {
        return null;
    }
}

// 不管key是否存在都會執行put操作
// 如果指定函數返回值爲null,則代表刪除該key
default V compute(K key,
                  BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
    Objects.requireNonNull(remappingFunction);
    V oldValue = get(key);

    V newValue = remappingFunction.apply(key, oldValue);
    if (newValue == null) {
        // delete mapping
        if (oldValue != null || containsKey(key)) {
            // something to remove
            remove(key);
            return null;
        } else {
            // nothing to do. Leave things as they were.
            return null;
        }
    } else {
        // add or replace old mapping
        put(key, newValue);
        return newValue;
    }
}

// 如果key不存在或者key存在但是value==null,執行put(key, value),否則執行put(key, function)
// 如果指定函數返回值爲null,則代表刪除該key
default V merge(K key, V value,
                BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
    Objects.requireNonNull(remappingFunction);
    Objects.requireNonNull(value);
    V oldValue = get(key);
    V newValue = (oldValue == null) ? value :
    remappingFunction.apply(oldValue, value);
    if(newValue == null) {
        remove(key);
    } else {
        put(key, newValue);
    }
    return newValue;
}

示例

特別需要注意Key存在但是Value值爲null的情況

Map<String, Integer> map = new HashMap<>(16);
map.put("s", 0);
map.put("s1", 1);
// getOrDefault 不會修改map數據
System.out.println(map.getOrDefault("s2", 2)); // return 2
System.out.println(map); // {s=0, s1=1}

// replaceAll
map.replaceAll((k, v) -> v * 2);
System.out.println(map); // {s=0, s1=2}

// putIfAbsent
// 1.key不存在,執行put("s2", null)
System.out.println(map.putIfAbsent("s2", null)); // return oldValue null
System.out.println(map); // {s=0, s1=2, s2=null}
// 2.key存在,value==null,執行put("s2", 100)
System.out.println(map.putIfAbsent("s2", 100)); // return oldValue null
System.out.println(map); // {s=0, s1=2, s2=100}
// 2.key存在,value!=null,什麼都不做
System.out.println(map.putIfAbsent("s2", 200)); // return oldValue 100
System.out.println(map); // {s=0, s1=2, s2=100}

// remove(Object key, Object value)
// 1.key不存在,什麼都不做
System.out.println(map.remove("s3", null)); // return false
// 2.key存在,但是value不匹配,什麼都不做
System.out.println(map.remove("s2", 200)); // return false
// 3.key存在並且value匹配,執行remove("s2")
System.out.println(map.remove("s2", 100)); // return true
System.out.println(map); // {s=0, s1=2}

// replace(K key, V oldValue, V newValue)
// 1.key不存在,什麼都不做
System.out.println(map.replace("s2", 200, 300)); // return false
// 2.key存在,oldValue不匹配,什麼都不做
System.out.println(map.replace("s1", 200, 300)); // return false
// 3.key存在並且oldValue匹配,執行put("s1", null)
System.out.println(map.replace("s1", 2, null)); // return true
// 4.key存在並且oldValue匹配, value==null,執行put("s1, 400")
System.out.println(map.replace("s1", null, 400)); // return true
System.out.println(map); // {s=0, s1=400}

// replace(K key, V value)
// 1.key不存在,什麼都不做
System.out.println(map.replace("s2", 200)); // return oldValue null
// 2.key存在,value!=null,執行put("s1", null)
System.out.println(map.replace("s1", null)); // return oldValue 400
// 3.key存在,value==null,執行put("s1", 500)
System.out.println(map.replace("s1", 500)); // return oldValue null
System.out.println(map); // {s=0, s1=500}

// computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)
Function<Integer, Integer> function = item -> item * 2;
// 1.key不存在,執行put("s2", 500 * 2)
System.out.println(map.computeIfAbsent("s2", k -> function.apply(500))); // return newValue 1000
// 2.key存在,value==null,執行put("s2", 600 * 2)
map.put("s2", null);
System.out.println(map.computeIfAbsent("s2", k -> function.apply(600))); // return newValue 1200
// 3.key存在,value!=null,什麼都不做
System.out.println(map.computeIfAbsent("s2", k -> function.apply(700))); // return oldValue 1200
System.out.println(map); // {s=0, s1=500, s2=1200}

// computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
// 1.key不存在,什麼都不做
System.out.println(map.computeIfPresent("s3", (k, v) -> v * 3)); // return null
// 2.key存在,value==null,什麼都不做
map.put("s2", null);
System.out.println(map.computeIfPresent("s2", (k, v) -> v * 3)); // return null
// 3.key存在,value!=null,執行put("s1", 500 * 3)
System.out.println(map.computeIfPresent("s1", (k, v) -> v * 3)); // return newValue 1500
// 4.key存在,value!=null,指定函數返回null,執行remove("s1")
System.out.println(map.computeIfPresent("s1", (k, v) -> null)); // return null
System.out.println(map); // {s=0, s2=null}

// compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
// 1.key不存在,執行put("s1", 0)
System.out.println(map.compute("s1", (k, v) -> {
    if (v == null) return 0;
    return v + 1;
})); // return newValue 0
// 2.key存在,value==null,執行put("s2", 0)
System.out.println(map.compute("s2", (k, v) -> {
    if (v == null) return 0;
    return v + 1;
})); // return newValue 0
// 3.key存在,value!=null,執行put("s2", 1)
System.out.println(map.compute("s2", (k, v) -> {
    if (v == null) return 0;
    return v + 1;
})); // return newValue 1
// 4.key存在,指定函數返回null,執行remove("s2")
System.out.println(map.compute("s2", (k, v) -> null)); // return null
System.out.println(map); // {s=0, s1=0}

// merge
// 1.key不存在,執行put("s2", 1)
System.out.println(map.merge("s2", 1, (k, v) -> v + 1)); // return newValue 1
// 2.key存在,value!=null,執行put("s2", 1 + 1)
System.out.println(map.merge("s2", 1, (k, v) -> v + 1)); // return newValue 2
// 3.key存在,value==null,執行put("s2", 1)
map.put("s2", null);
System.out.println(map.merge("s2", 1, (k, v) -> v + 1)); // return newValue 1
// 4.指定函數返回null,則執行remove("s2")
System.out.println(map.merge("s2", 1, (k, v) -> null)); // return get(key) == null ? value : function
System.out.println(map); // {s=0, s1=0}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章