• Java源码记录


    路径java.util.AbstractMap

    ()构造方法

    /**
     * 唯一的构造器。(一般由子类隐式调用)
     */
    protexted AbstractMap(){
    }
    

    size()返回当前map的大小

    public int size() {
        return entrySet().size();
    }
    

    这里的entrySet()返回一个Set<Entry<K,V>>对象。但是当前类AbstractMap没有实现它。下同

    isEmpty()判断当前Map是否为空

    public boolean isEmpty() {
        return size() == 0;
    }
    

    containsKey(Object key)是否包含指定key

    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()方法,使用迭代器检查每一个EntryKey
    当参数key为空时,有任何一个Entrykey值为空则返回true
    当参数key不为空时,参数keyequals方法与任何一个key返回true时本方法返回true
    其他情况返回false

    get(Object key)获取指定val

    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;
    }
    

    containsKey(Object key)相同,返回值由bool变成了EntrygetVale的返回值
    其他情况下,返回null

    put(K key, V value)添加一个键值对

    public V put(K key, V value) {
        throw new UnsupportedOperationException();
    }
    

    直接抛出异常UnsupportedOperationException

    remove(Object key)删除指定键值

    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;
    }
    

    基于entrySet(),获取到对应Entry后,缓存其val,并在迭代器中删除找到的Entry,然后返回val

    putAll(Map<? extends K, ? extends V> m)添加指定Map中的键值对到当前当前Map

    public void putAll(Map<? extends K, ? extends V> m) {
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
            put(e.getKey(), e.getValue());
    }
    

    基于entrySet(),迭代调用put(K key, V value)方法进行操作
    本类中put(K key, V value)的实现为直接抛出UnsupportedOperationException()异常

    clear() 清空Map

    public void clear() {
        entrySet().clear();
    }
    

    直接清空entrySet()所返回的Set集合

    视图keySetvalues

    transient Set<K>        keySet;
    transient Collection<V> values;
    

    这两个变量主要用于keySet()values()方法。

    Set<K> keySet()获取key集合

    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;
    }
    

    此方法会初始化成员变量keySet并保持它的单例(因为没有做同步处理,所以有可能在并发环境下返回不同的对象)。
    此方法构造的Set集合实际类型为AbstractSet的匿名内部类,主要有如下实现

    1. iterator()方法的实现每次构造一个新的Iterator对象,并在内部保存外部类的entrySet()iterator()方法所返回的迭代器对象。作为委派目标i
    2. 新的Iterator对象的hasNext(), next(),remove()方法均委托到变量i
    3. AbstractSet其他的实现方法size(), isEmpty(), clear(),contains(Object k)全部委托到外部类AbstractMap的同名方法

    这里发生了一次数据上的可能的分离,就是iterator()所返回对象内部对象i来自entrySet().iterator(),而此时其他的方法如size()使用的实际方法为entrySet().size(),有可能会发生数据不同步的情况

    values() 获取值集合

    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;
    }
    

    keySet()相同,只是返回类型换为允许重复元素AbstractCollection

    equals(Object o)比较两个Map是否相同

    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;
    }
    

    比较流程如下

    1. 如果是同一个对象,则返回true
    2. 如果入参不是Map的子类,直接返回false
    3. 如果两者的size()返回的数量不同,直接返回false
    4. 使用entrySet().iterator()获取当前对象的迭代器并进行迭代。进行如下操作
    5. 迭代中。当val为空时,使用key向入参map进行值获取,结果值不为空或不包含这个key时,返回false
    6. 迭代中。当val为不空时,使用key向入参map进行值获取,当使用equals比较两者不相同时,返回false
    7. 迭代中出现ClassCastExceptionNullPointerException返回false
    8. 执行到结尾,返回true

    hashCode()获取HashCode

    public int hashCode() {
        int h = 0;
        Iterator<Entry<K,V>> i = entrySet().iterator();
        while (i.hasNext())
            h += i.next().hashCode();
        return h;
    }
    

    迭代所有Entry,累加所有EntryHashCode

    clone()clone当前对象

    protected Object clone() throws CloneNotSupportedException {
        AbstractMap<?,?> result = (AbstractMap<?,?>)super.clone();
        result.keySet = null;
        result.values = null;
        return result;
    }
    

    注意,这里是浅拷贝,并对新对象的keySetvalues属性进行置空
    由于当前抽象类的绝大多数实现是基于方法entrySet()方法,所以这个方法需要由实现类进行关注。防止浅拷贝后,新对象指向老引用引发问题

  • 相关阅读:
    最长有效括号
    C++ 环形缓存区的实现
    vector的原理与底层实现
    聚合分析与分组
    求两个数的最大公约数
    单例模式
    工厂方法模式
    责任链模式
    适配器模式
    策略模式
  • 原文地址:https://www.cnblogs.com/heaven-elegy/p/11787320.html
Copyright © 2020-2023  润新知