本篇中学习所用源码为 java8 版本。

首先看 Map 这个接口,Map 中一共有14个抽象方法    

Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法

//返回当前 Map 中元素的个数    
     int size();
    //Map 是否包含指定的  key
    boolean containsKey(Object key);
    // Map 是否包含指定的 value
    boolean containsValue(Object value);
    //返回 key 对应的 value
    V get(Object key);
    //放入 键值对
    V put(K key, V value);
    //移除键值对
    V remove(Object key);
    
    void putAll(Map<? extends K, ? extends V> m);
    // 清空Map 
    void clear();
    
    Set<K> keySet();
    //获取Map集合的value集合
    Collection<V> values();

    Set<Map.Entry<K, V>> entrySet();

   
    interface Entry<K,V> {
       
        K getKey();

        V getValue();

        V setValue(V value);

        boolean equals(Object o);

        int hashCode();

        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());
        }
       
        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());
        }

        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());
        }

        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());
        }
    }


    boolean equals(Object o);
   
    int hashCode();

   // 扩展方法 在Map 中没有找到指定键对应的值时返回一个默认值  具体参考例一
    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);
        }
    }

    //扩展方法  传入一个函数(方法) 以方法的结果值替换 Map 中相应键对应的值  具体参考实例三
    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为空或则键值对不存在,则用参数value覆盖
    default V putIfAbsent(K key, V value) {
        V v = get(key);
        if (v == null) {
            v = put(key, value);
        }

        return v;
    }

    //移除一个元素
    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;
    }

   
    //当键值对存在时 替换 value
    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;
    }

    //当键值对存在时 替换 value 并将原 value 返回,不存在时返回 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为空,函数才起作用。使用remappingFunction根据key计算出value,如果value不为null,则赋值或者添加;value为空则方法失效,不做任何改变
    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不为空,方法生效,通过键值对计算出新的value,不为空则赋值,为空就删去原有的键值对
    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;
        }
    }

    //使用remappingFunction根据键值对计算一个新的value,不为空就覆盖,或者添加;为空则删除原键值对
    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得到集合中value,如果value不为空,则使用 remappingFunction根据旧value和新value计算出一个结果去覆盖集合中原有的value,如果value为空,则直接用参数key,value覆盖.如果计算结果为null则删除原有键值对
    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;
    }
}

例一:getOrDefault 方法使用 以及和之前的对比

// JDK8之前的实现方法
String capitalGeorgia = statesAndCapitals.get("Georgia");
if (capitalGeorgia == null)
{
   capitalGeorgia = "Unknown";
}

// JDK8的实现方法
final String capitalWisconsin = statesAndCapitals.getOrDefault("Wisconsin", "Unknown");

示例二:Map 接口中默认方法 forEach 使用方式 以及和之前的对比

Map<String,String> map = new HashMap<String,String>();
        map.put("a", "q");
        map.put("b", "w");
        map.put("c", "e");
        
        //之前的遍历方式 1
        for (Map.Entry<String,String> entry : map.entrySet()) {
            System.out.println("key:"+entry.getKey()+";value:"+entry.getValue());
        }
        //之前的遍历方式 2
        Set<String> keySet = map.keySet();
        for (String entry : keySet) {
            System.out.println("key:"+ entry +";value:" + map.get(entry));
        }
        //新式 forEach 应用1
        map.forEach((k, v) -> System.out.println("key" + ":" + k + ";" + "value" + ":" + v));
        //新式 forEach 应用2
        map.forEach((m, n) -> {
            if (m.equals("a")) {
                System.out.println("条件判断");
            } else {
                System.out.println(n);
            }
        });

 实例三:Map 接口中默认方法 replaceAll使用方式

Map<String,String> map = new HashMap<String,String>();
        map.put("a", "q");
        map.put("b", "w");
        map.put("c", "e");
        
        
        map.replaceAll((k, v) -> k.length() + "");