今天来看一下AbstractMap这个类。它是HashMap的直接父类,根据JDK文档上的说法,这个类的作用在于简化Map的实现。如果你想实现一个Map,直接继承AbstractMap,然后是实现其中一部分的方法就可以了。
老规矩,先看类定义
public abstract class AbstractMap<K,V> implements Map<K,V>
特点:1 抽象类,不允许实例化
2 实现了Map接口
继续往下看,接下来是构造函数
protected AbstractMap() {
}
构造函数,通常被子类隐式调用
public int size() {
return entrySet().size();
}
返回Map内键值对的数量,实现方式是获取EntrySet的数量
public boolean isEmpty() {
return size() == 0;
}
判断集合是不是有元素
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;
}
是否包含某个值。
主要分为两种情况,参数value是不是null,然后通过迭代器遍历对比,当然也是借助Entry实现
判断是否包含某个键
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;
}
原理同containValue
根据Key获取数据
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();
}
不支持插入数据,需要子类自己实现
根据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;
}
先拿到这个key所对应的entry,然后使用迭代器移除,然后返回value
将一个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());
}
类似于Collection的addAll
清空Map
public void clear() {
entrySet().clear();
}
获取键的set集合
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;
}
手动实现了一个匿名AbstractSet
获取value 的集合
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;
}
原理类似
AbstractMap重写的equals,还是很有意思的
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;
}
入参是Object类型,首先判断是不是当前对象。
然后判断是不是一个Map对象(是不是map的实现类或者实现类的子类),如果是的话强转为Map对象,然后再判断元素数量是否一致。不一致肯定返回false。
然后我们就开始遍历当前对象,拿到每一个元素对应的key和value,如果每一个key和value的映射关系在参数中都一一对应,吗,那么就返回true。
总而言之,判断两个AbstractMap相同需要键值对的映射关系也是完全一致的才可以。
public int hashCode() {
int h = 0;
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext())
h += i.next().hashCode();
return h;
}
map的hashcode是集合内元素的hashcode的累和。
剩下的两个内部类没看出来作用,以后有了新发现再记录