吃透Java集合系列八:Map

2019-12-08  本文已影响0人  吃透Java

文章首发csdn博客地址:https://blog.csdn.net/u013277209?viewmode=contents

Map接口分析

关于Map接口,JDK是这样描述的:

public interface Map<K,V> {
    //增
    /**
     * put方法是将指定的key-value存储到map里面的操作.如果map之前包含了一个此key对应的映射,
     * 那么此key对应的旧value值会被新的value值替换.
     */
    V put(K key, V value);
    /**
     * putAll方法是将一个指定map的映射拷贝到当前map.这一操作类似于将指定map的key-value对通过put方法一个个拷贝过来。
     * 在拷贝过程中,如果指定的这个map被更改了,那么这时候会出现什么情况,并不清楚。
     */
    void putAll(Map<? extends K, ? extends V> m);
    
    //删
    /**
     * remove方法用于移除map中已有的某个key.更一般的讲,如果map包含了一个满足条件key==null ?  k==null : key.equals(k)的映射,
     * 这一映射就会被移除.(map最多包含一个这样的映射)
     * 本方法会返回移除的key对应的value值,如果map这个key没有对应的value值,则返回null。
     * 如果map允许null值,那么返回null值并不一定表明map不包含对应key的映射值;因为这也可能是key本身对应的value值就是null.
     */
    V remove(Object key);
    /**
     * 移除map中所有的映射
     */
    void clear();

    //查
    /**
     * 返回map中key-value映射的个数.如果map包含的key-value个数超过了Integer.MAX_VALUE这个数
     * 则返回Integer.MAX_VALUE.
     */
    int size();

    /**
     * 如果map没有存储任何key-value,则返回true
     */
    boolean isEmpty();
    /**
     * 如果map存储了指定的key,则返回true.更一般的情况是,当且仅当map包含了一个key的映射
     * 映射情况是:key==null ? k==null : key.equals(k),此时返回true.
     */
    boolean containsKey(Object key);

    /**
     * 如果map中至少有一个key能映射到指定的value,那么就返回true.更一般的情况是,
     * 当且仅当value==null ? v==null : value.equals(v)条件成立,才返回true.
     * 在所有map接口的实现类中,这一操作都需要map大小的线性时间来完成.
     */
    boolean containsValue(Object value);

    /**
     * 返回指定key映射的value.如果map没有指定的key,则返回null.
     */
    V get(Object key);

    //三个返回key,value,key-value的集合
    /**
     * 此方法:返回map包含所有的key的一个set集合视图
     */
    Set<K> keySet();
    /**
     * values方法返回map内存储的所有值的集合(毕竟值集合中,值可以有重复的,所以此方法和上面的返回的
     * key集合的结果类型不一样,因为key肯定都是不同的).
     */
    Collection<V> values();

    /**
     * 此方法返回map里存储的所有映射的视图.
     */
    Set<Map.Entry<K, V>> entrySet();

    //两个覆盖object的方法
     /**
     * 用于对比两个map是否相等.
     * 如果给定的对象是一个map且两个map的映射一致,则返回true.
     * 一般,两个map的映射一致,要满足的条件是:m1.entrySet().equals(m2.entrySet())
     * 这就保证了实现了map接口的不同类对于equals方法的使用才是正确的.
     */
    boolean equals(Object o);

    /**
     * 返回map的哈希值,map的哈希值被定义为:这个map的entrySet视图的每一个条目的哈希值的总和.
     * 这就保证了任意两个map相等,则他们的哈希值一定相等,这也是Object类对哈希值的普遍要求(哈希值作为两个对象相等的必要非充分条件).
     */
    int hashCode();

    /**
     * map条目(key-value对),Map.entrySet方法返回的就是map的集合视图,map视图中的元素就是来源于此类.
     * 获取map条目的唯一方式就是来源于集合视图的迭代器.只有在迭代的过程中,Map.Entry对象才是有效的;
     * 通常,如果通过迭代器获得的map条目,在遍历过程中,作为后台支持的map被修改了,那么map条目会如何被影响,对此
     * 并没有做出具体规定(当然此处说的map修改不包括setValue方法的调用).
     */
    interface Entry<K,V> {
        /**
         * 获取当前map条目对应的key
         */
        K getKey();

        /**
         * 返回map条目对应的value值.
         */
        V getValue();

        /**
         * 用指定值替换当前条目中的value
         */
        V setValue(V value);

        /**
         * 将指定对象和当前条目做比较,如果给定的对象是一个条目并且两个条目代表同一个映射,则返回true.
         */
        boolean equals(Object o);

        /**
         * 返回map条目的哈希值
         */
        int hashCode();

        /**
         * 返回一个比较map.entry的比较器,按照key的自然顺序排序,返回的比较器支持序列化
         * @since 1.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());
        }

        /**
         * 返回一个map.enty的比较器,按照value的自然顺序排序,返回的比较器支持序列化
         * @since 1.8
         */
        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的比较器,根据传入比较器对key排序,如果传入的比较器支持序列化,则返回的结果比较器也支持序列化.
         * @since 1.8
         */
        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());
        }

        /**
         * 返回一个map.entry的比较器,根据传入比较器对value排序,如果传入的比较器支持序列化,则返回的结果比较器也支持序列化
         * @since 1.8
         */
        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.8新增
    /**
     * 返回指定key对应的value,如果没有对应的映射,则返回传入参数中的默认值defaultValue
     * @since 1.8
     */
    default V getOrDefault(Object key, V defaultValue) {
        V v;
        return (((v = get(key)) != null) || containsKey(key))
            ? v
            : defaultValue;
    }

    /**
     * 对map中每一个entry执行action中定义对操作,直到全部entry执行完成or执行中出现异常为止
     * @since 1.8
     */
    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中每一个entry,将其value替换成BiFunction接口返回的值.直到所有entry替换完or出现异常为止
     * @since 1.8
     */
    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);
            }
        }
    }

    /**
     * 如果指定的键尚未与值相关联(或被映射为null),则将它与给定的值相关联并返回null,否则返回当前值。
     * @since 1.8
     */
    default V putIfAbsent(K key, V value) {
        V v = get(key);
        if (v == null) {
            v = put(key, value);
        }

        return v;
    }

    /**
     * 如果给定的参数key和value在map中是一个entry,则删除这个entry.
     * @since 1.8
     */
    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在map中有entry,则为指定key的entry,用新value替换旧的value
     * @since 1.8
     */
    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在map中有value,则用参数value进行替换
     * @since 1.8
     */
    default V replace(K key, V value) {
        V curValue;
        if (((curValue = get(key)) != null) || containsKey(key)) {
            curValue = put(key, value);
        }
        return curValue;
    }

    /**
     * 如果指定key在map中没有对应的value,则使用输入参数,即函数接口mappingfunction为其计算一个value.
     * 如果计算value不为null,则将value插入map中,如果计算function返回结果为null,则不插入任何映射。
     * @since 1.8
     */
    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;
    }

    /**
     * 如果map中存在指定key对应的value,且不为null,则本方法会尝试使用function,并利用key生成一个新的value
     * 如果function接口返回null,map中原entry则被移除.如果function本身抛出异常,则当前map不会发生改变.
     * @since 1.8
     */
    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和value计算一个新映射,比如:向一个value映射中新增或者拼接一个String。
     * 如果function接口返回null,则map中原entry被移除(如果本来就不存在,则不执行移除操作).
     * 如果function本身抛出(非检查型)异常,异常会被重新抛出,当前map也不会发生改变.
     * @since 1.8
     */
    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为null,则将其改为给定的非null的value
     * 否则,用给定的function返回值替换原value.
     * 如果给定参数value和function返回结果都为null,则删除map中这个entry.
     * 这一方法常用于:对一个key合并多个映射的value时.
     * 比如:要创建或追加一个String给一个值映射.
     * 如果function返回null,则map中原entry被移除.如果function本身抛出异常,则异常会被重新抛出,且当前map不会发生更改.
     * @since 1.8
     */
    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;
    }
}
    
}

上述注释按照JDK进行翻译,如有不正确支出,望提出。

上一篇下一篇

猜你喜欢

热点阅读