---恢复内容开始---
AbstractMap类是一个抽象类,与map接口类不同的是,abstractmap是map的一个“skeletal implementation”(骨架实现),用处是减少实现map接口的工作量。
首先,我们需要看一下这个类的内部实体类SimpleEntry
public static class SimpleEntry<K,V> implements Entry<K,V>, java.io.Serializable { private static final long serialVersionUID = -8499721149061103585L; private final K key; private V value; public SimpleEntry(K key, V value) { this.key = key; this.value = value; } public SimpleEntry(Entry<? extends K, ? extends V> entry) { this.key = entry.getKey(); this.value = entry.getValue(); } public K getKey() { return key; } public V getValue() { return value; } public V setValue(V value) { V oldValue = this.value; this.value = value; return oldValue; } public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry e = (Map.Entry)o; return eq(key, e.getKey()) && eq(value, e.getValue()); } public int hashCode() { return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()); } public String toString() { return key + "=" + value; } }
代码如上,很明显的看出就是一个实体类数据集合,包含一个key2value的对象,同时提供了object类的接口实现,很明显的看出来,entry类的equals比较方法,是进行key值对比和value对比,hashCode()方法会进行key的hash和value的hash进行异或操作,而若某值为空,也会产生hash为0的现状。
之后我们看看abstractmap对这个数据集怎么进行处理的。
public abstract Set<Entry<K,V>> entrySet();
此为该操作对象集,实现的map接口,同时也可以继承上面的simpleentry进行改写。显而易见作为一个set集,代表其中没有重复的内容,保证不重复的关键就是key值不重复。
public int size() { return entrySet().size(); }
size返回的也是数据集的大小。
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; }
containsValue主要是迭代器遍历,还针对value是否为空进行分叉,主要也是因为equals会被重写。
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; }
same old things
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; }
get也是通过迭代器进行的查找,比较蛋疼,居然是遍历,然后根据key值对应的value进行操作,感觉时间复杂度还是比较大的。
public V put(K key, V value) { throw new UnsupportedOperationException(); }
这个就是必须要复写了,否则就爆异常。
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; }