Java源码记录 - AbstractMap

路径java.util.AbstractMap

()构造方法

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

size()返回当前map的大小

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

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

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

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

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

public boolean containsKey(Object key) {
    Iterator> i = entrySet().iterator();
    if (key==null) {
        while (i.hasNext()) {
            Entry e = i.next();
            if (e.getKey()==null)
                return true;
        }
    } else {
        while (i.hasNext()) {
            Entry 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> i = entrySet().iterator();
    if (key==null) {
        while (i.hasNext()) {
            Entry e = i.next();
            if (e.getKey()==null)
                return e.getValue();
        }
    } else {
        while (i.hasNext()) {
            Entry 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> i = entrySet().iterator();
    Entry correctEntry = null;
    if (key==null) {
        while (correctEntry==null && i.hasNext()) {
            Entry e = i.next();
            if (e.getKey()==null)
                correctEntry = e;
        }
    } else {
        while (correctEntry==null && i.hasNext()) {
            Entry 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 m)添加指定Map中的键值对到当前当前Map

public void putAll(Map m) {
    for (Map.Entry 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        keySet;
transient Collection values;

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

Set keySet()获取key集合

public Set keySet() {
    Set ks = keySet;
    if (ks == null) {
        ks = new AbstractSet() {
            public Iterator iterator() {
                return new Iterator() {
                    private Iterator> 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 values() {
    Collection vals = values;
    if (vals == null) {
        vals = new AbstractCollection() {
            public Iterator iterator() {
                return new Iterator() {
                    private Iterator> 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> i = entrySet().iterator();
        while (i.hasNext()) {
            Entry 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> 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()方法,所以这个方法需要由实现类进行关注。防止浅拷贝后,新对象指向老引用引发问题

你可能感兴趣的:(Java源码记录 - AbstractMap)