JDK源码阅读之AbstractMap

AbstractMap简介

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

AbstractMap是实现map接口,并且将大部分的方法实现。

要实现不可修改的映射,编程人员只需扩展此类并提供 entrySet 方法的实现即可,该方法将返回映射的映射关系 set 视图。通常,返回的 set 将依次在 AbstractSet 上实现。此 set 不支持 add 或 remove 方法,其迭代器也不支持 remove 方法。

AbstractMap提供了读取和查询映射的方法,如果你想自己写一个不可改变的映射集合,那么继承这个类并且提供实现entrySet的方法即可。

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

AbstractMap有put方法,但是他没有一个具体的实现,而是直接将错误抛出。所以如果想实现可以修改的映射集合,那么要重写这个方法。

AbstractMap类图

AbstractMap类图
AbstractMap就实现了一个map接口,AbstractMap是map的努力实现。

AbstractMap重要方法

构造方法

protected AbstractMap() {
    }

仅有的无参构造方法

Contians方法

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

检验是否包含key或value,检验的方法也是使用迭代器直接循环集合,然后调用对象的equals方法判断是都相等。另外注意到:方法都会有对null的检验,也就是说AbstractMap是支持null值和null键的。

get

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

这个方法和上一个方法也是一样的,都是使用迭代器循环然后对比得出结果。如果没有结果则返回null。

remove

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

如果存在一个键的映射关系,则将其从此映射中移除。首先是检测是否存在映射,然后移除,使用的是迭代器的remove方法。

keyset 、values

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

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

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

这两个方法都是一样的,只是返回的一个是键的集合一个是值的集合。如果AbstractMap中的键或值为空,那么他会新建一个AbstractMap实现的Collection集合。

clone

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

返回此 AbstractMap 实例的浅表副本:不复制键和值本身。

AbstractMap源码阅读感想

AbstractMap是尽努力实现Map接口的方法,也就是定义一些Map方法的实现,让map的实现更加的容易。在阅读完源码之后,我觉得map的大部分方法都是通过迭代器去完成的。例如查找,根据迭代器来迭代查找,移除方法,是用迭代器的remove方法。

说明

本文是本人撰写,如果本文让你有些许收获或感悟,我感到荣幸。如果对这篇文章有不同的意见或发现错误,欢迎留言纠正或者联系我:zlh8013gsf@126.com

©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页