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就实现了一个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