AbstractMap類是Map接口的子類,實(shí)現(xiàn)了Map接口大部分方法,它的子類只需要實(shí)現(xiàn)Set<Entry<K,V>> entrySet() 返回一個鍵值對的集合,就可以使用Map集合的功能了。
一.AbstractMap抽樣類
1.1 添加方法
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
直接拋出異常,如果子類不復(fù)寫這個方法,那么它是一個不可修改的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());
}
遍歷Map集合m,通過它的entrySet()方法得到可迭代的Set集合,然后將每個鍵值對存放到本Map集合中。
1.2 刪除方法
public V remove(Object key) {
// 得到鍵值對的迭代器
Iterator<Entry<K,V>> i = entrySet().iterator();
Entry<K,V> correctEntry = null;
// 根據(jù)key是否為null,分成兩部分,雖然這兩部分代碼邏輯幾乎一樣
// 這樣做主要是減少判斷,因?yàn)楹铣梢徊糠值脑?,判斷條件就要增加
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;
// 如果找這個鍵值對correctEntry,刪除它,并返回它的value值
if (correctEntry !=null) {
oldValue = correctEntry.getValue();
i.remove();
}
return oldValue;
}
通過entrySet().iterator()方法,得到鍵值對的迭代器,然后遍歷鍵值對,找到與key值相等的鍵值對,刪除它,并返回對應(yīng)的value值,如果沒找到,就返回null。
public void clear() {
entrySet().clear();
}
調(diào)用entrySet集合的clear()方法。
1.3 查找元素
public boolean containsKey(Object key) {
// 得到鍵值對的迭代器
Iterator<Map.Entry<K,V>> i = entrySet().iterator();
// 根據(jù)key是否為null,分成兩部分
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;
}
通過entrySet().iterator()方法,得到鍵值對的迭代器,然后遍歷鍵值對,找到與key值相等的鍵值對,返回true,否則返回false。
public boolean containsValue(Object value) {
// 得到鍵值對的迭代器
Iterator<Entry<K,V>> i = entrySet().iterator();
// 根據(jù)value是否為null,分成兩部分,
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().iterator()方法,得到鍵值對的迭代器,然后遍歷鍵值對,找到與value值相等的鍵值對,返回true,否則返回false。
public V get(Object key) {
// 得到鍵值對的迭代器
Iterator<Entry<K,V>> i = entrySet().iterator();
// 根據(jù)key是否為null,分成兩部分,
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;
}
通過entrySet().iterator()方法,得到鍵值對的迭代器,然后遍歷鍵值對,找到與key值相等的鍵值對,并返回對應(yīng)的value值,如果沒找到,就返回null。
1.4 遍歷Map集合。
我們知道Map接口可以返回三個集合,分別是key值組成的Set<K>集合,value值組成的Collection<V>集合,以及鍵值對組成的Set<Map.Entry<K, V>>集合。
其實(shí)這里面最重要的是鍵值對組成的Set集合,因?yàn)槠渌麅蓚€集合是可以通過這個集合得到。
public Set<K> keySet() {
// 使用keySet變量做緩存用的,這樣只有第一次時需要遍歷entrySet()集合。
Set<K> ks = keySet;
if (ks == null) {
// 創(chuàng)建一個Set集合,對它的操作都調(diào)用Map集合對應(yīng)方法。
ks = new AbstractSet<K>() {
public Iterator<K> iterator() {
// 創(chuàng)建一個迭代器,利用 entrySet().iterator()的迭代器來實(shí)現(xiàn)本Iterator實(shí)例的方法。
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;
}
public Collection<V> values() {
// 使用values變量做緩存用的,防止每次都遍歷創(chuàng)建
Collection<V> vals = values;
if (vals == null) {
// 創(chuàng)建一個Collection集合,對它的操作都調(diào)用Map集合對應(yīng)方法。
vals = new AbstractCollection<V>() {
public Iterator<V> iterator() {
// 創(chuàng)建一個迭代器,利用 entrySet().iterator()的迭代器來實(shí)現(xiàn)本Iterator實(shí)例的方法。
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的內(nèi)部類 SimpleEntry
SimpleEntry實(shí)現(xiàn)了Map.Entry接口,表示一個簡單地鍵值對類。它有兩個成員屬性key、value來存儲鍵值對。
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;
// 構(gòu)造函數(shù)時,就傳入key值和value值
public SimpleEntry(K key, V value) {
this.key = key;
this.value = value;
}
// 或者使用另一個entry來初始化key值和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;
}
// 替換value值,并返回原來的oldValue值
public V setValue(V value) {
V oldValue = this.value;
this.value = value;
return oldValue;
}
// 當(dāng)key值與value值都相等時,就說明兩個entry值相等
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());
}
// 保證兩個相等的entry,它們的hashCode值必須也相同
public int hashCode() {
return (key == null ? 0 : key.hashCode()) ^
(value == null ? 0 : value.hashCode());
}
public String toString() {
return key + "=" + value;
}
}
AbstractMap的內(nèi)部類 SimpleImmutableEntry
SimpleImmutableEntry表示一個不可修改鍵值對Entry類,也就是說它的setValue(V value)方法會直接拋出異常,其他方法與SimpleEntry類一樣。
public static class SimpleImmutableEntry<K,V>
implements Entry<K,V>, java.io.Serializable
{
private static final long serialVersionUID = 7138329143949025153L;
private final K key;
private final V value;
// 構(gòu)造函數(shù)時,就傳入key值和value值
public SimpleImmutableEntry(K key, V value) {
this.key = key;
this.value = value;
}
// 當(dāng)key值與value值都相等時,就說明兩個entry值相等
public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry) {
this.key = entry.getKey();
this.value = entry.getValue();
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
// 因?yàn)槭遣豢尚薷逆I值對Entry類,所以setValue方法直接拋出異常
public V setValue(V value) {
throw new UnsupportedOperationException();
}
// 當(dāng)key值與value值都相等時,就說明兩個entry值相等
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());
}
// 保證兩個相等的entry,它們的hashCode值必須也相同
public int hashCode() {
return (key == null ? 0 : key.hashCode()) ^
(value == null ? 0 : value.hashCode());
}
public String toString() {
return key + "=" + value;
}
}
總結(jié)
AbstractMap抽樣類
- 強(qiáng)制子類復(fù)寫Set<Entry<K,V>> entrySet()方法。
- V put(K key, V value):直接拋出異常,如果不復(fù)寫這個方法,那么集合是不能添加數(shù)據(jù)的。
- void putAll(Map<? extends K, ? extends V> m):是遍歷集合,然后調(diào)用put方法,將元素添加到集合中,所以也會拋出異常。
- V remove(Object key):調(diào)用entrySet集合迭代器的remove()實(shí)現(xiàn)的,并返回移除的value值。
- void clear():調(diào)用entrySet集合迭代器的clear()方法實(shí)現(xiàn)的。
- boolean containsKey(Object key):通過entrySet集合迭代器來遍歷Map集合,查找key值相同元素。
- containsValue(Object value):通過entrySet集合迭代器來遍歷Map集合,查找value值相同元素。
- V get(Object key):通過entrySet集合迭代器來遍歷Map集合,查找key值相同鍵值對元素,并返回value值。如果沒找到就返回null。
- Set<K> keySet():創(chuàng)建一個Set集合,實(shí)現(xiàn)都是調(diào)用entrySet集合對應(yīng)方法。
10.Collection<V> values():創(chuàng)建一個Collection集合,實(shí)現(xiàn)都是調(diào)用entrySet集合對應(yīng)方法。
AbstractMap的內(nèi)部類 SimpleEntry和SimpleImmutableEntry
都是實(shí)現(xiàn)了Map.Entry接口,表示一個簡單地鍵值對類。它有兩個成員屬性key、value來存儲鍵值對。
唯一不同的是SimpleImmutableEntry表示一個不可修改鍵值對Entry類,,也就是說它的setValue(V value)方法會直接拋出異常。