Java源碼記錄 - AbstractMap

路徑java.util.AbstractMap

()構造方法

/**
 * 惟一的構造器。(通常由子類隱式調用)
 */
protexted AbstractMap(){
}

size()返回當前map的大小

public int size() {
    return entrySet().size();
}

這裏的entrySet()返回一個Set<Entry<K,V>>對象。可是當前類AbstractMap沒有實現它。下同java

isEmpty()判斷當前Map是否爲空

public boolean isEmpty() {
    return size() == 0;
}

containsKey(Object key)是否包含指定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;
}

一樣依靠entrySet()方法,使用迭代器檢查每個EntryKey
當參數key爲空時,有任何一個Entrykey值爲空則返回true
當參數key不爲空時,參數keyequals方法與任何一個key返回true時本方法返回true
其餘狀況返回false緩存

get(Object key)獲取指定val

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;
}

containsKey(Object key)相同,返回值由bool變成了EntrygetVale的返回值
其餘狀況下,返回null併發

put(K key, V value)添加一個鍵值對

public V put(K key, V value) {
    throw new UnsupportedOperationException();
}

直接拋出異常UnsupportedOperationExceptionthis

remove(Object 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;
}

基於entrySet(),獲取到對應Entry後,緩存其val,並在迭代器中刪除找到的Entry,而後返回valcode

putAll(Map<? extends K, ? extends V> m)添加指定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());
}

基於entrySet(),迭代調用put(K key, V value)方法進行操做
本類中put(K key, V value)的實現爲直接拋出UnsupportedOperationException()異常對象

clear() 清空Map

public void clear() {
    entrySet().clear();
}

直接清空entrySet()所返回的Set集合rem

視圖keySetvalues

transient Set<K>        keySet;
transient Collection<V> values;

這兩個變量主要用於keySet()values()方法。get

Set<K> keySet()獲取key集合

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;
}

此方法會初始化成員變量keySet並保持它的單例(由於沒有作同步處理,因此有可能在併發環境下返回不一樣的對象)。
此方法構造的Set集合實際類型爲AbstractSet的匿名內部類,主要有以下實現同步

  1. iterator()方法的實現每次構造一個新的Iterator對象,並在內部保存外部類的entrySet()iterator()方法所返回的迭代器對象。做爲委派目標i
  2. 新的Iterator對象的hasNext(), next(),remove()方法均委託到變量i
  3. AbstractSet其餘的實現方法size(), isEmpty(), clear(),contains(Object k)所有委託到外部類AbstractMap的同名方法

這裏發生了一次數據上的可能的分離,就是iterator()所返回對象內部對象i來自entrySet().iterator(),而此時其餘的方法如size()使用的實際方法爲entrySet().size(),有可能會發生數據不一樣步的狀況hash

values() 獲取值集合

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;
}

keySet()相同,只是返回類型換爲容許重複元素AbstractCollection

equals(Object o)比較兩個Map是否相同

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;
}

比較流程以下

  1. 若是是同一個對象,則返回true
  2. 若是入參不是Map的子類,直接返回false
  3. 若是二者的size()返回的數量不一樣,直接返回false
  4. 使用entrySet().iterator()獲取當前對象的迭代器並進行迭代。進行以下操做
  5. 迭代中。當val爲空時,使用key向入參map進行值獲取,結果值不爲空或不包含這個key時,返回false
  6. 迭代中。當val爲不空時,使用key向入參map進行值獲取,當使用equals比較二者不相同時,返回false
  7. 迭代中出現ClassCastExceptionNullPointerException返回false
  8. 執行到結尾,返回true

hashCode()獲取HashCode

public int hashCode() {
    int h = 0;
    Iterator<Entry<K,V>> i = entrySet().iterator();
    while (i.hasNext())
        h += i.next().hashCode();
    return h;
}

迭代全部Entry,累加全部EntryHashCode

clone()clone當前對象

protected Object clone() throws CloneNotSupportedException {
    AbstractMap<?,?> result = (AbstractMap<?,?>)super.clone();
    result.keySet = null;
    result.values = null;
    return result;
}

注意,這裏是淺拷貝,並對新對象的keySetvalues屬性進行置空
因爲當前抽象類的絕大多數實現是基於方法entrySet()方法,因此這個方法須要由實現類進行關注。防止淺拷貝後,新對象指向老引用引起問題

相關文章
相關標籤/搜索