• 【JDK】JDK源码分析-Map


    Map 接口

    Map 是一个接口,它表示一种“键-值(key-value)”映射的对象(Entry),其中键是不重复的(值可以重复),且最多映射到一个值(可以理解为“映射”或者“字典”)。

    Map 常用的实现类有 HashMap、TreeMap、ConcurrentHashMap、LinkedHashMap 等,它们的继承结构如下:

    Map 的方法列表如下:

    一些常用方法:

    // 将键-值对存入 Map,若 key 对应的 value 已存在,则将其替换
    // 返回原先 key 对应的 value(若不存在,返回 null)
    V put(K key, V value);
    
    // 将指定 Map 中的所有元素拷贝到本 Map 中
    void putAll(Map<? extends K, ? extends V> m);
    
    // 返回本 Map 中所有 key 的 Set 视图
    Set<K> keySet();
    
    // 返回本 Map 中所有 value 的 Collection 视图
    Collection<V> values();
    
    // 返回本 Map 中所有 Entry 的 Set 视图
    // 其中 Entry 是 Map 内部的一个接口,可以理解为 Map 的“元数据”
    Set<Map.Entry<K, V>> entrySet();

    此外,JDK 1.8 又增加了不少方法,如下:

    // 获取 key 对应的 value,若 value 为 null,则返回 defaultValue
    default V getOrDefault(Object key, V defaultValue) {
        V v;
        return (((v = get(key)) != null) || containsKey(key))
            ? v
            : defaultValue;
    }
    
    // 遍历 Map 中的元素
    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);
        }
    }
    
    // 通过给定的函数计算出新的 Entry 替换所有旧的 Entry
    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) {
                // this usually means the entry is no longer in the map.
                throw new ConcurrentModificationException(ise);
            }
            // ise thrown from function is not a cme.
            v = function.apply(k, v);
            try {
                entry.setValue(v);
            } catch(IllegalStateException ise) {
                // this usually means the entry is no longer in the map.
                throw new ConcurrentModificationException(ise);
            }
        }
    }
    
    // 若 key 对应的 value 不存在,则把 key-value 存入 Map,否则无操作
    default V putIfAbsent(K key, V value) {
        V v = get(key);
        if (v == null) {
            v = put(key, value);
        }
    
        return v;
    }
    
    // 若 key 对应的值等于 value,则移除 key;否则无操作
    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 对应的值等于 oldValue,则将其替换为 newValue;否则无操作
    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;
    }
    
    // Map 中存在 key 时,将 key-value 存入,相当于:
    /*
      if (map.containsKey(key)) {
          return map.put(key, value);
      } else
          return null;
      }
     */
    default V replace(K key, V value) {
        V curValue;
        if (((curValue = get(key)) != null) || containsKey(key)) {
            curValue = put(key, value);
        }
        return curValue;
    }
    
    // 当 key 对应的 value 不存在时,使用给定的函数计算得出 newValue
    // 并将 key-newValue 存入 Map
    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 存在时,使用给定的函数计算得出 newValue,
    // 当 newValue 不为 null 时将 key-newValue 存入 Map;否则移除 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 和其对应的 oldValue,使用给定的函数计算出 newValue
    // 若 newValue 为 null
    //   若 oldValue 不为空或 key 存在,则删除 key-oldValue
    //   否则无操作
    // 若 newValue 不为 null,用 newValue 替换 oldValue
    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;
        }
    }
    
    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;
    }

    PS: 1.8 中的几个方法看似比较复杂,但有些方法实质上相当于对一些 if...else 语句的封装,利用 lambda 表达式可以让代码更简洁。

    Entry 接口

    Map 接口内部还定义了一个 Entry 接口(上面已经出现),它其实相当于 Map 内部存储的「元数据」,也就是 键-值(key-value) 映射。方法列表如下:

    其中前面几个方法都比较简单,这里分析下后面几个 JDK 1.8 引入的方法,如下:

    // 返回一个比较器,它以自然顺序比较 Entry 的 key
    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());
    }
    
    // 返回一个比较器,它以自然顺序比较 Entry 的 value
    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());
    }
    
    // 返回一个比较器,它使用给定的 Comparator 比较 Entry 的 key
    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 比较 Entry 的 value
    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());
    }

    小结

    1. Map 接口虽然没有继承自 Collection 接口,但也是 JCF(Java Collections Framework) 的一部分;

    2. Map 存储的是键-值(key-value)映射结构的对象;

    3. Entry 接口定义在其内部,它是真正定义键-值映射的结构,相当于 Map 的「元数据」。

    Stay hungry, stay foolish.

    PS: 本文首发于微信公众号【WriteOnRead】。

  • 相关阅读:
    Xcode 8.2 想使用插件 怎么办? 教你科学的使用插件
    JSAPI_Ticket签名
    Java中HashMap,LinkedHashMap,TreeMap的区别[转]
    微信支付开发,再次签名,APP调用
    微信支付开发,统一下单
    android studio安装插件
    java实现mysql数据库的备份及还原
    java项目中读取src目录下的文件
    eclipse增加浏览器chrome
    cd 命令
  • 原文地址:https://www.cnblogs.com/jaxer/p/11117495.html
Copyright © 2020-2023  润新知