java容器体系(六)----Map(AbstractMap)

  AbstratMap 是实现了 Map 接口的抽象类,它定义了一系列的方法体,供子类直接使用,如子类HashMap。

一、成员变量

  AbstractMap 只定义了两个成员变量 keySet 和 values。

/**
  * 注意:
  * 1、这两个内部变量都使用 transient 进行修饰,在子类实现了 Cloneable 接口的情况下,这两个成员变量也不会被序列化
  * 2、这两个变量都没有使用访问权限修饰符(public/protected/private)进行修饰,也就是说他们对于AbstractMap和与AbstractMap同包中的类(java.util)可见,
* 因为没有使用protected进行修饰,因而不同包的子类不可见 *
*/ transient Set<K> keySet; transient Collection<V> values;

 二、内部方法

public abstract class AbstractMap<K,V> implements Map<K,V> {
    /**
     * 唯一的构造器,并使用 protected 进行修饰
     */
    protected AbstractMap() {
    }

    /**
     * 返回的是 Map 中键值对(key-value)的数量
     */
    public int size() {
        return entrySet().size();
    }

    /**
     * 判断键值对数量是否为0,关键需要看entrySet()返回的Set的元素数量
     */
    public boolean isEmpty() {
        return size() == 0;
    }

    /**
     * 判断Map是否存在值为value的键值对(需要线性时间,跟size()大小有关)
     */
    public boolean containsValue(Object value) {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        if (value==null) { // value = null时,直接调用Entry.getValue()判断是否为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())) // 使用equals判断
                    return true;
            }
        }
        return false;
    }

    /**
     * 判断Map是否存在键为key的键值对,实现形式与containsValue方法类似(需要线性时间,跟size()大小有关)
     */
    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;
    }

    /**
     * 使用的是迭代器遍历entrySet,键等于key时,返回entry 的value值
     */
    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();
    }

    /**
     * 根据键删除键值对,使用的是迭代器遍历,找到相应键的键值对,使用迭代器的remove()方法,返回找到的键值对的value值
     */
    public V remove(Object key) {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        Entry<K,V> correctEntry = null; // 需要删除的键值对Entry
        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;
    }


    /**
     * 遍历输入参数的Map的entry集合,每次调用put方法存入当前Map中
     */
    public void putAll(Map<? extends K, ? extends V> m) {
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) /* foreach语法糖实际上使用的也是迭代器遍历,返回的Set实现了Collection接口,Collection接口实现了Itearable接口,
        因此Collection均可直接使用forEach或者迭代器直接遍历,Map需要使用entrySet()进行遍历键值对*/
            put(e.getKey(), e.getValue());
    }

    /**
     * Map清空,通过entrySet() 完成清空
     */
    public void clear() {
        entrySet().clear();
    }

    /**
     * 获取Map中键的集合(Set无重复)
     */
    public Set<K> keySet() {
        Set<K> ks = keySet; // AbstractMap成员变量Set<K> keySet
        if (ks == null) { // 没有调用过keySet()方法时,ks就是null
            ks = new AbstractSet<K>() { // 直接实现AbstractSet的成员方法
                public Iterator<K> iterator() {
                    return new Iterator<K>() { // 使用匿名类的形式,实现了Iterator内部的方法
                        private Iterator<Entry<K,V>> i = entrySet().iterator(); // 同样是entrySet的迭代器

                        public boolean hasNext() {
                            return i.hasNext();
                        }

                        public K next() {
                            return i.next().getKey(); // 注意:获取的是entry的key
                        }

                        public void remove() {
                            i.remove();
                        }
                    };
                }

                public int size() {
                    return AbstractMap.this.size(); // entrySet().size(),这个元素数量是entrySet的数量,因为键值对的键本身就不重复,它的数量就代表keySet的size
                }

                public boolean isEmpty() {
                    return AbstractMap.this.isEmpty(); // entrySet().size() == 0
                }

                public void clear() {
                    AbstractMap.this.clear(); // entrySet().clear()
                }

                public boolean contains(Object k) {
                    return AbstractMap.this.containsKey(k);
                }
            };
            keySet = ks;
        }
        return ks;
    }

    /**
     * 返回的是Map键值对中值得集合(有重复)
     */
    public Collection<V> values() {
        Collection<V> vals = values;
        if (vals == null) { // 没有调用过values()方法,vals就是null
            vals = new AbstractCollection<V>() { // 直接实现AbstractCollection内部方法
                public Iterator<V> iterator() {
                    return new Iterator<V>() {
                        private Iterator<Entry<K,V>> i = entrySet().iterator(); // 返回的entrySet迭代器

                        public boolean hasNext() {
                            return i.hasNext();
                        }

                        public V next() {
                            return i.next().getValue(); // 注意:获取的是entry的value
                        }

                        public void remove() {
                            i.remove();
                        }
                    };
                }

                public int size() {
                    return AbstractMap.this.size(); // entrySet().size(),这个元素数量是entrySet的数量,不是键值对中值得数量,重复元素计算为多个
                }

                public boolean isEmpty() { 
                    return AbstractMap.this.isEmpty(); // entrySet().size() == 0
                }

                public void clear() {
                    AbstractMap.this.clear(); // entrySet().clear()
                }

                public boolean contains(Object v) {
                    return AbstractMap.this.containsValue(v);
                }
            };
            values = vals;
        }
        return vals;
    }

    public abstract Set<Entry<K,V>> entrySet(); // entrySet 具体由子类实现

    /**
     * 判断两个Map的内容是否相同
     */
    public boolean equals(Object o) {
        if (o == this) // 1、两个Map引用地址相同时,直接返回true
            return true;

        if (!(o instanceof Map)) // 2、o 不是Map类型时,直接返回false
            return false;
        Map<?,?> m = (Map<?,?>) o;
        if (m.size() != size()) // 3、转为Map类型的 o 两者键值对数量不等时,直接返回false
            return false;

        try { // 4、通过遍历比较
            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))) // 加上containsKey(key)是因为如HashMap允许值为null
                        return false;
                } else {
                    if (!value.equals(m.get(key)))
                        return false;
                }
            }
        } catch (ClassCastException unused) {
            return false;
        } catch (NullPointerException unused) {
            return false;
        }

        return true;
    }

    /**
     * AbstractMap 的hashCode()实现方式直接将所有的Entry的hashCode相加返回。。。
     */
    public int hashCode() {
        int h = 0;
        Iterator<Entry<K,V>> i = entrySet().iterator();
        while (i.hasNext())
            h += i.next().hashCode();
        return h;
    }

    /**
     * 重写了toString()方法
     */
    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(' ');
        }
    }

    /**
     *    
     * @return Map的浅拷贝,keySet和values不会被拷贝
     */
    protected Object clone() throws CloneNotSupportedException {
        AbstractMap<?,?> result = (AbstractMap<?,?>)super.clone();
        result.keySet = null;
        result. = null;
        return result;
    }

    /**
     * 比较两个对象是否相等
     */
    private static boolean eq(Object o1, Object o2) {
        return o1 == null ? o2 == null : o1.equals(o2);
    }

}

三、内部类

   AbstractMap 还提供了两个静态内部类SimpleEntry、SimpleImmutableEntry,它们均实现了Map.Entry接口和Serializable接口。Map.

Entry 代表了一个键值对。

1、SimpleEntry

/**
     * @since 1.6
     */
    public static class SimpleEntry<K,V>
        implements Entry<K,V>, java.io.Serializable
    {
        private static final long serialVersionUID = -8499721149061103585L;

        private final K key; // final修饰,初始化后不能修改
        private V value;

        /**
         * SimpleEntry构造函数
         */
        public SimpleEntry(K key, V value) {
            this.key   = key;
            this.value = value;
        }

        /**
         * 传入Entry参数的构造函数
         */
        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;
        }

        /**
         * 覆盖Entry中的value,返回原来的值
         */
        public V setValue(V value) {
            V oldValue = this.value;
            this.value = value;
            return oldValue;
        }

        /**
         * 比较两个Entry是否相等,即比较key和value是否都相等
         */
        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的hashCode()方法时将key和value的hashCode进行异或取值
         */
        public int hashCode() {
            return (key   == null ? 0 :   key.hashCode()) ^
                   (value == null ? 0 : value.hashCode());
        }

        /**
         * 重写了toString
         */
        public String toString() {
            return key + "=" + value;
        }

    }

2、SimpleImmutableEntry

/**
     * 不允许Entry覆盖value的Entry实现
     * @since 1.6
     */
    public static class SimpleImmutableEntry<K,V>
        implements Entry<K,V>, java.io.Serializable
    {
        private static final long serialVersionUID = 7138329143949025153L;

        // key和value都使用了final修饰,初始化后不可以修改
        private final K key;
        private final V value;

        /**
         * SimpleImmutableEntry构造函数
         */
        public SimpleImmutableEntry(K key, V value) {
            this.key   = key;
            this.value = value;
        }

        /**
         * 传入Entry参数的构造函数
         */
        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) { //与SimpleEntry不同的地方,不允许覆盖value,直接抛出异常(可以看到抛出异常后,返回值也不需要写了)
            throw new UnsupportedOperationException();
        }

        /**
         * 比较Map.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());
        }

        /**
         * key和value hashCode()异或取值
         */
        public int hashCode() {
            return (key   == null ? 0 :   key.hashCode()) ^
                   (value == null ? 0 : value.hashCode());
        }

        /**
         * 重写了toString
         */
        public String toString() {
            return key + "=" + value;
        }

    }

 

posted @ 2020-09-21 15:27  Sunrise2750  阅读(173)  评论(0)    收藏  举报