zoukankan      html  css  js  c++  java
  • 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表达式这在很大程度上简化了编程代码的代码量。

  • 相关阅读:
    IE6,IE7 DIV高度技巧(div高度兼容问题)
    QQ在线咨询插件
    Singleton单件 (创建型模式)
    SQL Server ErrorLog 错误日志(如果数据库所占空间变大)
    IE6 div标签height的Bug
    c# 中 Volatile关键字理解
    翻译:SWFObject 2.0官方文档(用来做flash的js)
    已连接到空闲例程的问题解决办法
    Oracle 的一个非常好的触发器例子
    Oracle中表的非常全面的操作
  • 原文地址:https://www.cnblogs.com/IdealSpring/p/11871199.html
Copyright © 2011-2022 走看看