Map容器家族(Map接口源码详解)

一、在Map集合体系中的位置及概述

        Map接口式是Map集合体系的顶层接口,它定义和规范了该集合体系的大体规范,所有子类该实现的方法。该体系是以键值对(key-value)对位元素进行存储。

       描述:

       (1)映射(map)是一个存储键、键值对的对象,给定一个键,可以查询得到它的值,键和值都可以是对象。
       (2)键必须是唯一的,值可以重复(Map接口映射唯一的键到值)
       (3)有些映射可以接收null键和null值,而有的不行
       (4)下面的接口支持映射:
              Map接口 映射唯一关键字给值
              Map.Entry接口 描述映射中的元素(关键字/值对),这是Map的一个内部类
              SortedMap接口 扩展Map以便关键字按升序保持

       (5)键(Key)是以后用于检索值的对象,给定一个键和一个值,可以存储这个值到一个Map对象中,以后可以
       使用对应的键来检索它

二、约束子类必须实现的方法

1.查询操作(Query Operations)

    /**
     * 功能:查询元素个数
     */
    int size();

    /**
     * 功能:是否为空
     */
    boolean isEmpty();

    /**
     * 功能:判断键是否存在
     */
    boolean containsKey(Object key);

    /**
     * 功能:判断值是否存在
     */
    boolean containsValue(Object value);

    /**
     * 功能:根据键获取值
     */
    V get(Object key);

2.修改操作(Modification Operations)

    /**
     * 功能:向map集合中添加键值对,如果键原来没有返回null,如果有返回被替换的值
     */
    V put(K key, V value);

    /**
     * 功能:根据key移除键值对,并返回值
     */
    V remove(Object key);

3.批量操作(Bulk Operations)

    /**
     * 功能:批量添加map集合
     */
    void putAll(Map<? extends K, ? extends V> m);

    /**
     * 功能:清空map集合中的所有键值对
     */
    void clear();

4.视图操作(Views)

    /**
     * 功能:返回map集合中所有键的Set集合
     */
    Set<K> keySet();

    /**
     * 功能:返回map集合中所有值的Collection集合
     */
    Collection<V> values();

    /**
     * 功能:返回map集合中所有键值对的Entry表示形式的Set集合
     */
    Set<Map.Entry<K, V>> entrySet();

5.键值对视图接口(interface Entry<K,V>),该接口的方法如下:

        该接口的作用是保存一个Key和Value键值对,和约束了一些操作键值的方法。

        /**
         * 功能:获取键
         */
        K getKey();

        /**
         * 功能:获取值
         */
        V getValue();

        /**
         * 功能:设置键的值
         */
        V setValue(V value);

        /**
         * 功能:比较是否相等
         */
        boolean equals(Object o);

        /**
         * 功能:返回hash码
         */
        int hashCode();

JDK1.8后新加的方法:

        /**
         * 功能:返回一个按键在自然顺序排序的比较器
         */
        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());
        }

 6.比较和哈希(Comparison and hashing)

    /**
     * 功能:比较是否相等
     */
    boolean equals(Object o);

    /**
     * 功能:返回哈希值
     */
    int hashCode();

7.JDK1.8新添加的default方法(Defaultable methods)

        default关键字是jdk1.8新添加的,它打破了接口中的方法不能有方法体的标准。

(1)获取方法 getOrDefault

    /**
     * 功能:返回指定键映射到的值,如果此映射不包含键的映射,则返回指定的默认值
     */
    default V getOrDefault(Object key, V defaultValue) {
        V v;
        return (((v = get(key)) != null) || containsKey(key))
            ? v
            : defaultValue;
    }

(2)遍历方法 forEcah

    /**
     * 功能:对每个键值对执行相同的操作,该操作使用lambda表达式定义
     * 注:BiConsumer函数式接口为两个输入
     */
    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<Integer, Integer> map = new HashMap<>();
        map.put(1, 1);
        map.put(2, 2);
        map.put(3, 3);

        map.forEach((x1, x2) -> System.out.println(x1 + "=" + x2));

(3)对所有值进行操作 raplaceAll

    /**
     * 功能:根据指定的操作,对所有键的值进行相同的操作
     * 注:BiFunction函数值接口为两个输入,一个输出
     */
    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);
            }
        }
    }

    使用方法演示

        Map<Integer, Integer> map = new HashMap<>();
        map.put(1, 1);
        map.put(2, 2);
        map.put(3, 3);

        // x1和x2分别为键和值的变量,x1+x2为对所有值的操作
        map.replaceAll((x1, x2) -> x1 + x2);
        map.forEach((x1, x2) -> System.out.println(x1 + "=" + x2));

(4)添加元素 putIfAbsent

    /**
     * 功能:如果map中没有指定的键,则put进该键值对
     */
    default V putIfAbsent(K key, V value) {
        V v = get(key);
        if (v == null) {
            v = put(key, value);
        }

        return v;
    }

(5)删除功能 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;
    }

(6)替换功能 

    /**
     * 功能:替换
     */
    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;
    }

    default V replace(K key, V value) {
        V curValue;
        if (((curValue = get(key)) != null) || containsKey(key)) {
            curValue = put(key, value);
        }
        return curValue;
    }

三、总结

        Map接口是对键值对形式存储的数据结构方法的约束,子类方法需要实现其规定的抽象方法。在JDK1.8之后又添加了一些default声明的方法去扩充它本身的方法,新添加的方法中有很大一部分是关于1.8后新引入的函数式接口的方法,我个人认使用Lambda表达式这在很大程度上简化了编程代码的代码量。

posted @ 2018-09-15 18:31  小情绪Ango  阅读(174)  评论(0编辑  收藏  举报