Java 集合框架_AbstractMap

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抽樣類

  1. 強(qiáng)制子類復(fù)寫Set<Entry<K,V>> entrySet()方法。
  2. V put(K key, V value):直接拋出異常,如果不復(fù)寫這個方法,那么集合是不能添加數(shù)據(jù)的。
  3. void putAll(Map<? extends K, ? extends V> m):是遍歷集合,然后調(diào)用put方法,將元素添加到集合中,所以也會拋出異常。
  4. V remove(Object key):調(diào)用entrySet集合迭代器的remove()實(shí)現(xiàn)的,并返回移除的value值。
  5. void clear():調(diào)用entrySet集合迭代器的clear()方法實(shí)現(xiàn)的。
  6. boolean containsKey(Object key):通過entrySet集合迭代器來遍歷Map集合,查找key值相同元素。
  7. containsValue(Object value):通過entrySet集合迭代器來遍歷Map集合,查找value值相同元素。
  8. V get(Object key):通過entrySet集合迭代器來遍歷Map集合,查找key值相同鍵值對元素,并返回value值。如果沒找到就返回null。
  9. 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)方法會直接拋出異常。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容