[toc] 引言 今天學習一個Java集合的一個抽象類 AbstractMap ,AbstractMap 是 Map 介面的 實現類之一,也是HashMap、TreeMap、ConcurrentHashMap 等的父類,它提供了 Map 介面中方法的基本實現(關於Map介面有疑惑的同學可參考 "Ja ...
目錄
引言
今天學習一個Java集合的一個抽象類 AbstractMap ,AbstractMap 是Map介面的 實現類之一,也是HashMap、TreeMap、ConcurrentHashMap 等的父類,它提供了Map 介面中方法的基本實現(關於Map介面有疑惑的同學可參考 Java集合類根介面:Collection 和 Map)
源碼解析
因為 AbstractMap 類是實現Map介面的抽象類,所以其內部也包含了操作子元素的實體介面 Entry,其源碼方法對元素的操作都是基於 Entry 的視圖實現的。
抽象函數entrySet()
AbstractMap類中有一個唯一的抽象函數 entrySet() ,類中對集合視圖操作的很多方法都是依賴這個抽象函數的,它返回一個保存所有 key-value 映射的Set。
當我們要實現一個不可變的 Map 時,只需要繼承 AbstractMap 類並實現 entrySet() 即可。
如果想要實現一個可變的 Map ,我們還需要重寫 put() 方法,因為 AbstractMap 類中預設不支持 put實現,子類必須重寫該方法的實現,否則會拋出異常:
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
在這裡,有人會疑惑為什麼必須重寫 put 方法呢,很大可能是官方考慮到也許會有不可修改的Map實現子類繼承 AbstractMap,如果 put 方法預設可以操作,那不可修改的子類就行不通了。
兩個集合視圖
AbstractMap沒有提供 entrySet() 的實現,但是卻提供了 keySet() 與 values() 集合視圖的預設實現,它們都是依賴於 entrySet() 返回的集合視圖實現的,這是他們的源碼:
- keySet()
// 返回一個AbstractSet的實現,包含了所有的key
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;
}
- values()
// 返回一個AbstractCollection的實現,包含了所有的value
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 的具體操作集合的方法。
- 添加
/**
* 沒有提供實現,子類必須重寫該方法,否則調用put()會拋出異常。
*/
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
/**
* 遍歷一個Map,然後將每一個鍵值對put到該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());
}
- 刪除
/**
* 遍歷entrySet,先找到對應的key的entry,然後刪除。
*/
public V remove(Object key) {
Iterator<Entry<K,V>> i = entrySet().iterator();
Entry<K,V> correctEntry = null;
//遍歷查找,當某個 Entry 的 key 和 指定 key 一致時結束
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();
//調用迭代器的 remove 方法
i.remove();
}
return oldValue;
}
/**
* 清空entrySet,等價於清空該Map。
*/
public void clear() {
entrySet().clear();
}
- 查詢對應的子元素
//遍歷entrySet(),看看是否包含參數key
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;
}
//與containsKey方法同理,只是比較的是value
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;
}
- 獲取元素
//使用 entrySet 迭代器進行遍歷,根據 key 查找,返回對應的value
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;
}
兩個子類
除了上面的方法之外,AbstractMap 類中還提供了兩個子類,分別是 SimpleEntry,SimpleImmutableEntry,兩個子類都實現了Map.Entry 以及 Serializable 介面,這是他們的源碼
- SimpleEntry
public static class SimpleEntry<K, V> implements Entry<K, V>, Serializable {
private static final long serialVersionUID = -8499721149061103585L;
private final K key;
private V value;
public SimpleEntry(K var1, V var2) {
this.key = var1;
this.value = var2;
}
public SimpleEntry(Entry<? extends K, ? extends V> var1) {
this.key = var1.getKey();
this.value = var1.getValue();
}
public K getKey() {
return this.key;
}
public V getValue() {
return this.value;
}
public V setValue(V var1) {
Object var2 = this.value;
this.value = var1;
return var2;
}
public boolean equals(Object var1) {
if (!(var1 instanceof Entry)) {
return false;
} else {
Entry var2 = (Entry)var1;
return AbstractMap.eq(this.key, var2.getKey()) && AbstractMap.eq(this.value, var2.getValue());
}
}
public int hashCode() {
return (this.key == null ? 0 : this.key.hashCode()) ^ (this.value == null ? 0 : this.value.hashCode());
}
public String toString() {
return this.key + "=" + this.value;
}
}
- SimpleImmutableEntry
public static class SimpleImmutableEntry<K, V> implements Entry<K, V>, Serializable {
private static final long serialVersionUID = 7138329143949025153L;
private final K key;
private final V value;
public SimpleImmutableEntry(K var1, V var2) {
this.key = var1;
this.value = var2;
}
public SimpleImmutableEntry(Entry<? extends K, ? extends V> var1) {
this.key = var1.getKey();
this.value = var1.getValue();
}
public K getKey() {
return this.key;
}
public V getValue() {
return this.value;
}
public V setValue(V var1) {
throw new UnsupportedOperationException();
}
public boolean equals(Object var1) {
if (!(var1 instanceof Entry)) {
return false;
} else {
Entry var2 = (Entry)var1;
return AbstractMap.eq(this.key, var2.getKey()) && AbstractMap.eq(this.value, var2.getValue());
}
}
public int hashCode() {
return (this.key == null ? 0 : this.key.hashCode()) ^ (this.value == null ? 0 : this.value.hashCode());
}
public String toString() {
return this.key + "=" + this.value;
}
}
兩個實現都非常簡單,具體的方法也是大同小異,唯一有區別的是 setValue 這個方法,SimpleEntry 支持 setValue 的操作實現,而 SimpleImmutableEntry 就沒有實現,說明前者為可變集合,後者為不可變集合。
參考:
http://www.importnew.com/29686.html