zoukankan      html  css  js  c++  java
  • Map容器家族(AbstractMap源码详解)

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

            AbstractMap抽象类提供Map接口的骨干实现,以最大限度地减少实现此接口所需的工作量。

    二、成员变量

        // 保存key
        transient Set<K>        keySet;
        // 保存value
        transient Collection<V> values;

    三、方法详解

    1.添加方法

        /**
         * 功能:向map中添加元素
         * 注:这个方法并没有实现
         */
        public V put(K key, V value) {
            throw new UnsupportedOperationException();
        }

    2.删除方法

        /**
         * 功能:删除所有键值对
         * 实现:
         * 1.调用Set集合的clear方法进行删除
         */
        public void clear() {
            entrySet().clear();
        }

    3.修改方法(Modification Operations)

        /**
         * 功能:根据键移除该键值对
         * 实现:
         * 1.获取保存Entry的Set迭代器,并创建临时保存要删除的Entry的变量correctEntry
         * 2.如果待删除的key为null:
         *      2.1 如果correctEntry中没有元素并且有下一个元素进行迭代,比较key值是否为null,如果为null将该Entry赋给correctEntry,迭代结束
         * 3.如果待删除的key不为null,操作同步骤2
         * 4.如果correctEntry为null,函数直接返回null
         * 5.如果correctEntry不为Null,将待删除的Entry值返回,并调用Set的remove方法删除该Entry
         */
        public V remove(Object key) {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            Entry<K,V> correctEntry = null;
            if (key==null) {
                while (correctEntry==null && i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (e.getKey()==null)
                        correctEntry = e;
                }
            } else {
                while (correctEntry==null && i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (key.equals(e.getKey()))
                        correctEntry = e;
                }
            }
    
            V oldValue = null;
            if (correctEntry !=null) {
                oldValue = correctEntry.getValue();
                i.remove();
            }
            return oldValue;
        }

    4.查询方法(Query Operations)

        /**
         * 功能:返回map元素个数
         * 实现:
         * 1.entrySet方法返回的是Set集合,调用Set集合的size方法获取键值对的个数
         */
        public int size() {
            return entrySet().size();
        }
    
        /**
         * 功能:该map集合是否为空
         * 实现:
         * 1.通过判断集合元素个数size是否为0即可判断是否为空
         */
        public boolean isEmpty() {
            return size() == 0;
        }
    
        /**
         * 功能:判断集合是否包含指定值
         * 功能:
         * 1.获取键值对的Set集合
         * 2.如果指定元素为null,使用Set迭代器遍历集合比较
         * 3.如果指定元素不为null,使用Set迭代器遍历集合比较
         * 4.如果没有找到返回false
         */
        public boolean containsValue(Object value) {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            if (value==null) {
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (e.getValue()==null)
                        return true;
                }
            } else {
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (value.equals(e.getValue()))
                        return true;
                }
            }
            return false;
        }
    
        /**
         * 功能:判断集合是否包含指定键
         * 实现:同上一个方法
         */
        public boolean containsKey(Object key) {
            Iterator<Map.Entry<K,V>> i = entrySet().iterator();
            if (key==null) {
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (e.getKey()==null)
                        return true;
                }
            } else {
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (key.equals(e.getKey()))
                        return true;
                }
            }
            return false;
        }
    
        /**
         * 功能:根据键获取值
         * 实现:
         * 1.获取键值对的Set集合
         * 2.如果指定的key为null,遍历集合,如果找到为null的key,则返回key
         * 3.如果指定的key不为空,遍历集合,如果找到key,则返回key
         * 4.如果没找到,则返回null
         */
        public V get(Object key) {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            if (key==null) {
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (e.getKey()==null)
                        return e.getValue();
                }
            } else {
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (key.equals(e.getKey()))
                        return e.getValue();
                }
            }
            return null;
        }

    5.批量操作(Bulk Operations)

        /**
         * 功能:添加一个map集合的元素到该集合中
         * 实现:
         * 1.使用增强for遍历该map的集合,使用put方法逐个添加
         */
        public void putAll(Map<? extends K, ? extends V> m) {
            for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
                put(e.getKey(), e.getValue());
        }

    6.视图

        /**
         * 功能:返回键的Set集合
         * 实现:
         * 1.将keySet的地址应用赋给ks
         * 2.如果ks没有为null(没有初始化),创建AbstractSet的子类并对其中的方法进行实现,获取到entrySet()
         *   的迭代器,就等同于获取到他的所有元素;
         * 3.返回ks
         * 
         * 注:
         *  1.这个方法的主体功能在调用的第一次会对keySet进行初始化,以后再次调用将不会执行主方法体,
         *    直接返回keySet。
         *  2.获取到一个结合迭代器在一定程度上就等同于获取到集合所有元素
         */
        public Set<K> keySet() {
            Set<K> ks = keySet;
            if (ks == null) {
                ks = new AbstractSet<K>() {
                    public Iterator<K> iterator() {
                        return new Iterator<K>() {
                            private Iterator<Entry<K,V>> i = entrySet().iterator();
    
                            public boolean hasNext() {
                                return i.hasNext();
                            }
    
                            public K next() {
                                return i.next().getKey();
                            }
    
                            public void remove() {
                                i.remove();
                            }
                        };
                    }
    
                    public int size() {
                        return AbstractMap.this.size();
                    }
    
                    public boolean isEmpty() {
                        return AbstractMap.this.isEmpty();
                    }
    
                    public void clear() {
                        AbstractMap.this.clear();
                    }
    
                    public boolean contains(Object k) {
                        return AbstractMap.this.containsKey(k);
                    }
                };
                keySet = ks;
            }
            return ks;
        }
    
        /**
         * 功能:获取所有的值,并以Collection集合的形式返回
         * 实现:原理同keySet方法
         */
        public Collection<V> values() {
            Collection<V> vals = values;
            if (vals == null) {
                vals = new AbstractCollection<V>() {
                    public Iterator<V> iterator() {
                        return new Iterator<V>() {
                            private Iterator<Entry<K,V>> i = entrySet().iterator();
    
                            public boolean hasNext() {
                                return i.hasNext();
                            }
    
                            public V next() {
                                return i.next().getValue();
                            }
    
                            public void remove() {
                                i.remove();
                            }
                        };
                    }
    
                    public int size() {
                        return AbstractMap.this.size();
                    }
    
                    public boolean isEmpty() {
                        return AbstractMap.this.isEmpty();
                    }
    
                    public void clear() {
                        AbstractMap.this.clear();
                    }
    
                    public boolean contains(Object v) {
                        return AbstractMap.this.containsValue(v);
                    }
                };
                values = vals;
            }
            return vals;
        }

    7.核心方法

        public abstract Set<Entry<K,V>> entrySet();

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

        /**
         * 功能:比较是否相等
         * 实现:
         * 1.如果o是本集合,则返回true
         * 2.如果o数据类型不是map,则返回false
         * 3.使用泛型通配符,将o转换成m
         * 4.获取本集合的Entry迭代器
         * 5.进行迭代分两种情况比较
         */
        public boolean equals(Object o) {
            if (o == this)
                return true;
    
            if (!(o instanceof Map))
                return false;
            Map<?,?> m = (Map<?,?>) o;
            if (m.size() != size())
                return false;
    
            try {
                Iterator<Entry<K,V>> i = entrySet().iterator();
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    K key = e.getKey();
                    V value = e.getValue();
                    if (value == null) {
                        if (!(m.get(key)==null && m.containsKey(key)))
                            return false;
                    } else {
                        if (!value.equals(m.get(key)))
                            return false;
                    }
                }
            } catch (ClassCastException unused) {
                return false;
            } catch (NullPointerException unused) {
                return false;
            }
    
            return true;
        }
    
        /**
         * 功能:返回次map集合的哈希值
         * 实现:
         * 1.遍历迭代每一个Entry,并将每个Entry的哈希值相加求和并返回
         */
        public int hashCode() {
            int h = 0;
            Iterator<Entry<K,V>> i = entrySet().iterator();
            while (i.hasNext())
                h += i.next().hashCode();
            return h;
        }

    9.其他方法

        /**
         * 功能:将map集合以字符串表示
         * 实现:一看就能懂
         */
        public String toString() {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            if (! i.hasNext())
                return "{}";
    
            StringBuilder sb = new StringBuilder();
            sb.append('{');
            for (;;) {
                Entry<K,V> e = i.next();
                K key = e.getKey();
                V value = e.getValue();
                sb.append(key   == this ? "(this Map)" : key);
                sb.append('=');
                sb.append(value == this ? "(this Map)" : value);
                if (! i.hasNext())
                    return sb.append('}').toString();
                sb.append(',').append(' ');
            }
        }
    
        /**
         * 功能:浅度克隆该map集合
         * 注:不克隆键和值的集合
         */
        protected Object clone() throws CloneNotSupportedException {
            AbstractMap<?,?> result = (AbstractMap<?,?>)super.clone();
            result.keySet = null;
            result.values = null;
            return result;
        }

    四、两个实现了Entry接口的静态方法

           这两个方法分别为SimpleEntry静态类和SimpleImmutableEntry静态类。这两个类的代码有99%都是相同的。只有setValue是不同的,SimpleEntry支持setValue功能而SimpleImmutableEntry不支持setValue方法,这也是这两个类的主要区别,即SimpleEntry是线程不安全的Entry的实现而SimpleImmutableEntry是线程安全的Entry的实现.

        /**
         * Map接口的Entry实现类
         */
        public static class SimpleEntry<K,V>
            implements Entry<K,V>, java.io.Serializable
        {
            private static final long serialVersionUID = -8499721149061103585L;
    
            // key值
            private final K key;
            // value值
            private V value;
    
            /**
             * 功能:构造方法
             */
            public SimpleEntry(K key, V value) {
                this.key   = key;
                this.value = value;
            }
    
            /**
             * 功能:构造方法
             */
            public SimpleEntry(Entry<? extends K, ? extends V> entry) {
                this.key   = entry.getKey();
                this.value = entry.getValue();
            }
    
            /**
             * 功能:获取键
             */
            public K getKey() {
                return key;
            }
    
            /**
             * 功能:获取值
             */
            public V getValue() {
                return value;
            }
    
            /**
             * 功能:设置值并返回以前的值
             */
            public V setValue(V value) {
                V oldValue = this.value;
                this.value = value;
                return oldValue;
            }
    
            /**
             * 功能:比较两个Entry是否相等
             */
            public boolean equals(Object o) {
                if (!(o instanceof Map.Entry))
                    return false;
                Map.Entry<?,?> e = (Map.Entry<?,?>)o;
                return eq(key, e.getKey()) && eq(value, e.getValue());
            }
    
            /**
             * 功能:返回此SimpleEntry的哈希值
             * 注:^ 为异或运算符
             */
            public int hashCode() {
                return (key   == null ? 0 :   key.hashCode()) ^
                       (value == null ? 0 : value.hashCode());
            }
    
            /**
             * 功能:返回此SimpleEntry的字符串表示
             */
            public String toString() {
                return key + "=" + value;
            }
    
        }
    
        public static class SimpleImmutableEntry<K,V>
            implements Entry<K,V>, java.io.Serializable
        {
            private static final long serialVersionUID = 7138329143949025153L;
    
            private final K key;
            private final V value;
    
            /**
             * 功能:构造方法
             */
            public SimpleImmutableEntry(K key, V value) {
                this.key   = key;
                this.value = value;
            }
    
            /**
             * 功能:构造方法
             */
            public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry) {
                this.key   = entry.getKey();
                this.value = entry.getValue();
            }
    
            /**
             * 功能:获取键
             */
            public K getKey() {
                return key;
            }
    
            /**
             * 功能:获取值
             */
            public V getValue() {
                return value;
            }
    
            /**
             * 功能:设置值
             * 注:此方法,为了保证线程安全,此类不实现
             */
            public V setValue(V value) {
                throw new UnsupportedOperationException();
            }
    
            /**
             * 功能:比较两个Entry是否相等
             */
            public boolean equals(Object o) {
                if (!(o instanceof Map.Entry))
                    return false;
                Map.Entry<?,?> e = (Map.Entry<?,?>)o;
                return eq(key, e.getKey()) && eq(value, e.getValue());
            }
    
            /**
             * 功能:返回此SimpleEntry的哈希值
             * 注:^ 为异或运算符
             */
            public int hashCode() {
                return (key   == null ? 0 :   key.hashCode()) ^
                       (value == null ? 0 : value.hashCode());
            }
    
            /**
             * 功能:返回此SimpleEntry的字符串表示
             */
            public String toString() {
                return key + "=" + value;
            }
    
        }

    五、总结

            AbstractMap抽象类提供Map接口的骨干实现,以最大限度地减少实现此接口所需的工作量。

            此类中有两个Map接口中Entry接口的静态实现,SimpleEntry类和SimpleImmutableEntry。SimpleEntry是线程安全的,SimpleImmutableEntry是线程不安全的。

  • 相关阅读:
    P1536 村村通 题解
    P1551 亲戚题解
    P1185 绘制二叉树 题解
    P3884 [JLOI2009]二叉树问题
    P1087 [NOIP2004 普及组] FBI 树
    P1305 新二叉树题解
    P1229 遍历问题
    P1030 [NOIP2001 普及组] 求先序排列题解
    P1827 [USACO3.4]美国血统 American Heritage 题解
    深度优先搜索dfs 讲解教程
  • 原文地址:https://www.cnblogs.com/IdealSpring/p/11871198.html
Copyright © 2011-2022 走看看