【集合类】源码解析之 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}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章