zoukankan      html  css  js  c++  java
  • jdk1.8.0_45源码解读——Map接口和AbstractMap抽象类的实现

    jdk1.8.0_45源码解读——Map接口和AbstractMap抽象类的实现

    一、 Map架构

    https://images0.cnblogs.com/blog/497634/201309/08221402-aa63b46891d0466a87e54411cd920237.jpg

    如上图:
    (01) Map 是映射接口,Map中存储的内容是键值对(key-value)
    (02) AbstractMap 是继承于Map的抽象类,它实现了Map中的大部分API。其它Map的实现类可以通过继承AbstractMap来减少重复编码。
    (03) SortedMap 是继承于Map的接口。SortedMap中的内容是排序的键值对,排序的方法是通过比较器(Comparator)。
    (04) NavigableMap 是继承于SortedMap的接口。相比于SortedMap,NavigableMap有一系列的导航方法;如"获取大于/等于某对象的键值对"、“获取小于/等于某对象的键值对”等等。
    (05) TreeMap 继承于AbstractMap,且实现了NavigableMap接口;因此,TreeMap中的内容是“有序的键值对”!
    (06) HashMap 继承于AbstractMap,但没实现NavigableMap接口;因此,HashMap的内容是“键值对,但不保证次序”!
    (07) Hashtable 虽然不是继承于AbstractMap,但它继承于Dictionary(Dictionary也是键值对的接口),而且也实现Map接口;因此,Hashtable的内容也是“键值对,也不保证次序”。但和HashMap相比,Hashtable是线程安全的,而且它支持通过Enumeration去遍历。
    (08) WeakHashMap 继承于AbstractMap。它和HashMap的键类型不同,WeakHashMap的键是“弱键”

    二、 Map接口

    1. Map.Entry<K, V>的结构

      映射项(键-值对)。Map.entrySet() 方法返回映射的 collection 视图,其中的元素属于此类。获得映射项引用的唯一 方法是通过此 collection 视图的迭代器来实现。这些 Map.Entry 对象在迭代期间有效;更确切地讲,如果在迭代器返回项之后修改了底层映射,则某些映射项的行为是不确定的,除了通过 setValue 在映射项上执行操作之外。

    K getKey();              //返回此项中对应的键值
    V getValue();          //返回此项中对应的值
    V setValue(V value);     //用指定的值替换与此项对应的值
    boolean equals(Object o);   //比较指定对象与此项的相等性
    int hashCode();         //返回此项的哈希码

    2. Map接口

    将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

    Map 接口提供三种collection 视图,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容。映射顺序 定义为迭代器在映射的 collection 视图上返回其元素的顺序。某些映射实现可明确保证其顺序,如 TreeMap 类;另一些映射实现则不保证顺序,如 HashMap 类。

    注:将可变对象用作映射键时必须格外小心。当对象是映射中某个键时,如果以影响 equals 比较的方式更改了对象的值,则映射的行为将是不确定的。此项禁止的一种特殊情况是不允许某个映射将自身作为一个键包含。虽然允许某个映射将自身作为值包含,但请格外小心:在这样的映射上 equalshashCode 方法的定义将不再是明确的。

    public interface Map<K,V> {
        int size();
        boolean isEmpty();
        boolean containsKey(Object key);
        boolean containsValue(Object value);
        V get(Object key);
        V put(K key, V value);
        V remove(Object key);
        void putAll(Map<? extends K, ? extends V> m);
        void clear(); 
        Set<K> keySet();
        Collection<V> values();
    
        //返回此映射中包含的映射关系的 set 视图
        Set<Map.Entry<K, V>> entrySet();
        boolean equals(Object o);
        int hashCode();
    }
       

    三、AbstractMap抽象类

    1. AbstractMap.SimpleEntry<K, V>的结构

      SimpleEntry<K, V>是维护键和值的 Entry。可以使用 setValue() 方法更改值。此类简化了构建自定义映射实现的过程。例如,可以使用 Map.entrySet().toArray 方法方便地返回 SimpleEntry实例数组。

        public static class SimpleEntry<K,V>
            implements Entry<K,V>, java.io.Serializable
        {
            private static final long serialVersionUID = -8499721149061103585L;
    
            private final K key;
            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;
            }
    
            //相等性检测,包括null值
            private static boolean eq(Object o1, Object o2) {
                return o1 == null ? o2 == null : o1.equals(o2);
            }
            
            //比较指定对象与此项的相等性
            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());
            }
    
            //返回此映射项的哈希值:key值的哈希码与value值的哈希码按位异或的结果
            public int hashCode() {
                return (key   == null ? 0 :   key.hashCode()) ^
                       (value == null ? 0 : value.hashCode());
            }
    
    
            //返回此映射项的 String表示形式:key=value
            public String toString() {
                return key + "=" + value;
            }
    
        }
    View Code

    2.AbstractMap.SimpleImmutableEntry<K,V>的结构

      SimpleImmutableEntry<K,V>是维护不可变的键和值的 Entry,不支持setValue()方法。方便用于在返回线程安全的键-值映射关系的方法。

        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;
            }
    
            //该方法仅抛出UnsupportedOperationException,表明该Entry不支持setValue方法
            public V setValue(V value) {
                throw new UnsupportedOperationException();
            }
    
            //比较指定对象与此项的相等性
            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());
            }
    
            //返回此映射项的哈希值:key值的哈希码与value值的哈希码按位异或的结果
            public int hashCode() {
                return (key   == null ? 0 :   key.hashCode()) ^
                       (value == null ? 0 : value.hashCode());
            }
    
            //返回此映射项的 String表示形式:key=value
            public String toString() {
                return key + "=" + value;
            }
        }
    View Code

    3. AbstractMap抽象类

    AbstractMap类提供 Map接口的骨干实现,以最大限度地减少实现此接口所需的工作。
    要实现不可修改的映射,编程人员只需扩展此类并提供 entrySet() 方法的实现即可,该方法将返回映射的映射关系 set视图。通常,返回的 set 将依次在 AbstractSet 上实现。此 set不支持 add() 或 remove() 方法,其迭代器也不支持 remove() 方法。

    要实现可修改的映射,编程人员必须另外重写此类的put() 方法(否则将抛出 UnsupportedOperationException),entrySet().iterator() 返回的迭代器也必须另外实现其 remove() 方法。

    public abstract class AbstractMap<K,V> implements Map<K,V> {
        //构造函数
        protected AbstractMap() {
        }
    
        //返回此映射中的键-值映射关系数
        public int size() {
            return entrySet().size();
        }
    
        //如果此映射未包含键-值映射关系,则返回 true。
        public boolean isEmpty() {
            return size() == 0;
        }
    
        //如果键值对<key,value>集合中包含指定的value值,则返回ture
        public boolean containsValue(Object value) {
            //entrySet()返回此映射中包含的映射关系的Set视图
            Iterator<Entry<K,V>> i = entrySet().iterator(); 
            //Map中允许value值为null,故分两种情况考虑
            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;
        }
    
        //如果键值对<key,value>集合中包含指定的key值,则返回ture
        public boolean containsKey(Object key) {
            //entrySet()返回此映射中包含的映射关系的Set视图
            Iterator<Map.Entry<K,V>> i = entrySet().iterator();
            //Map中只允许有唯一一个null的key值,故分两种情况考虑
            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;
        }
    
        //返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 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;
        }
    
        //将指定的值与此映射中的指定键关联
        public V put(K key, V value) {
            throw new UnsupportedOperationException();
        }
    
        /**
         * 如果存在一个键的映射关系,则将其从此映射中移除。并返回以前与key关联的值;如果没有key的映射关系,则返回null
         *
         * 注意,如果 entrySet()返回的集合所调用的迭代器不支持 remove方法,并且此映射包含指定键的映射关系,
         * 则此实现将抛出 UnsupportedOperationException。 
         */
        public V remove(Object key) {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            Entry<K,V> correctEntry = null; //用于指向给定键值对应的映射关系
            //找到指定键的映射关系,并赋值给correctEntry
            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(); //得到以前与key关联的值
                i.remove(); //运用迭代器中的remove()方法来对得到的键值对项进行移除工作
            }
            return oldValue;
        }
    
        //从指定Map中将所有映射关系<key,value>复制到此映射中
        public void putAll(Map<? extends K, ? extends V> m) {
            for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
                put(e.getKey(), e.getValue());
        }
    
        //从此映射中移除所有映射关系
        public void clear() {
            entrySet().clear();
        }
    
        //用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量最后修改后的值
        transient volatile Set<K>        keySet; //Map中key值的唯一性决定键值集合的视图类型为Set
        transient volatile Collection<V> values; //Map中value值的可重复性决定值集合的视图类型为Collection
    
        //返回此映射中包含的键的 Set视图
        public Set<K> keySet() {
            if (keySet == null) {
                keySet = 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);
                    }
                };
            }
            return keySet;
        }
    
        //返回此映射中包含的值的 Collection视图
        public Collection<V> values() {
            if (values == null) {
                values = 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(); //得到value值
                            }
    
                            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);
                    }
                };
            }
            return values;
        }
    
        //返回此映射中包含的映射关系的 Set 视图
        public abstract Set<Entry<K,V>> entrySet();
    
        //比较指定对象与此映射的相等性
        public boolean equals(Object o) {
            //如果给定对象也是一个映射并且两个映射表示相同的映射关系,则返回true
            if (o == this)
                return true;
            //检查指定的对象是否为映射关系
            if (!(o instanceof Map))
                return false;
            Map<?,?> m = (Map<?,?>) o; //强制类型转换
            //检查指定的对象是否是一个大小与此映射相等的映射
            if (m.size() != size())
                return false;
            //在此映射 entrySet()返回的collection上进行迭代,并检查指定的映射是否包含此映射所包含的每个映射关系
            try {
                Iterator<Entry<K,V>> i = entrySet().iterator();
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    K key = e.getKey(); //此映射的key值
                    V value = e.getValue(); //此映射的value值
                    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的哈希码被定义为该映射的 entrySet()视图中每个条目的哈希码之和。这确保了 m1.equals(m2)对于任意两个映射m1和m2都意味着 m1.hashCode()==m2.hashCode()
        public int hashCode() {
            int h = 0;
            Iterator<Entry<K,V>> i = entrySet().iterator();
            while (i.hasNext())
                h += i.next().hashCode();
            return h;
        }
    
        //返回此映射的字符串表示形式:{key1=value1}, {key1=value1}, ...
        public String toString() {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            if (! i.hasNext()) //Map为null
                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(' ');
            }
        }
    
        //返回此 AbstractMap 实例的浅表副本:不复制键和值本身
        protected Object clone() throws CloneNotSupportedException {
            AbstractMap<?,?> result = (AbstractMap<?,?>)super.clone();
            result.keySet = null;
            result.values = null;
            return result;
        }
    }
    View Code
  • 相关阅读:
    Windows 8实例教程系列 开篇
    qt 开发发布于 windeploy.exe
    qt qoci 测试验证
    vmware vmx 版本不兼容
    qt oracle
    vc qt dll
    QOCIDriver unable to create environment
    qoci 编译完 放置位置 具体根据情况
    calling 'lastError' with incomplete return type 'QSqlError' qsqlquer
    Hbase 操作工具类
  • 原文地址:https://www.cnblogs.com/CherishFX/p/4740113.html
Copyright © 2011-2022 走看看