Java 集合框架_AbstractMap

AbstractMap類是Map接口的子類,實(shí)現(xiàn)了Map接口大部分方法,它的子類只需要實(shí)現(xiàn)Set<Entry<K,V>> entrySet() 返回一個(gè)鍵值對(duì)的集合,就可以使用Map集合的功能了。

一.AbstractMap抽樣類

1.1 添加方法

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

直接拋出異常,如果子類不復(fù)寫這個(gè)方法,那么它是一個(gè)不可修改的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集合,然后將每個(gè)鍵值對(duì)存放到本Map集合中。

1.2 刪除方法

    public V remove(Object key) {
        // 得到鍵值對(duì)的迭代器
        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;
        // 如果找這個(gè)鍵值對(duì)correctEntry,刪除它,并返回它的value值
        if (correctEntry !=null) {
            oldValue = correctEntry.getValue();
            i.remove();
        }
        return oldValue;
    }

通過entrySet().iterator()方法,得到鍵值對(duì)的迭代器,然后遍歷鍵值對(duì),找到與key值相等的鍵值對(duì),刪除它,并返回對(duì)應(yīng)的value值,如果沒找到,就返回null。

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

調(diào)用entrySet集合的clear()方法。

1.3 查找元素

    public boolean containsKey(Object key) {
        // 得到鍵值對(duì)的迭代器
        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()方法,得到鍵值對(duì)的迭代器,然后遍歷鍵值對(duì),找到與key值相等的鍵值對(duì),返回true,否則返回false。

    public boolean containsValue(Object value) {
        // 得到鍵值對(duì)的迭代器
        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()方法,得到鍵值對(duì)的迭代器,然后遍歷鍵值對(duì),找到與value值相等的鍵值對(duì),返回true,否則返回false。

   public V get(Object key) {
        // 得到鍵值對(duì)的迭代器
        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()方法,得到鍵值對(duì)的迭代器,然后遍歷鍵值對(duì),找到與key值相等的鍵值對(duì),并返回對(duì)應(yīng)的value值,如果沒找到,就返回null。
1.4 遍歷Map集合。
我們知道Map接口可以返回三個(gè)集合,分別是key值組成的Set<K>集合,value值組成的Collection<V>集合,以及鍵值對(duì)組成的Set<Map.Entry<K, V>>集合。

其實(shí)這里面最重要的是鍵值對(duì)組成的Set集合,因?yàn)槠渌麅蓚€(gè)集合是可以通過這個(gè)集合得到。

    public Set<K> keySet() {
        // 使用keySet變量做緩存用的,這樣只有第一次時(shí)需要遍歷entrySet()集合。
        Set<K> ks = keySet;
        if (ks == null) {
            // 創(chuàng)建一個(gè)Set集合,對(duì)它的操作都調(diào)用Map集合對(duì)應(yīng)方法。
            ks = new AbstractSet<K>() {
                public Iterator<K> iterator() {
                    // 創(chuàng)建一個(gè)迭代器,利用 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)建一個(gè)Collection集合,對(duì)它的操作都調(diào)用Map集合對(duì)應(yīng)方法。
            vals = new AbstractCollection<V>() {
                public Iterator<V> iterator() {
                    // 創(chuàng)建一個(gè)迭代器,利用 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接口,表示一個(gè)簡(jiǎn)單地鍵值對(duì)類。它有兩個(gè)成員屬性key、value來存儲(chǔ)鍵值對(duì)。

    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ù)時(shí),就傳入key值和value值
        public SimpleEntry(K key, V value) {
            this.key   = key;
            this.value = value;
        }

        // 或者使用另一個(gè)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值都相等時(shí),就說明兩個(gè)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());
        }

        // 保證兩個(gè)相等的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表示一個(gè)不可修改鍵值對(duì)Entry類,也就是說它的setValue(V value)方法會(huì)直接拋出異常,其他方法與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ù)時(shí),就傳入key值和value值
        public SimpleImmutableEntry(K key, V value) {
            this.key   = key;
            this.value = value;
        }

        // 當(dāng)key值與value值都相等時(shí),就說明兩個(gè)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值對(duì)Entry類,所以setValue方法直接拋出異常
        public V setValue(V value) {
            throw new UnsupportedOperationException();
        }

        // 當(dāng)key值與value值都相等時(shí),就說明兩個(gè)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());
        }

        // 保證兩個(gè)相等的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ù)寫這個(gè)方法,那么集合是不能添加數(shù)據(jù)的。
  3. void putAll(Map<? extends K, ? extends V> m):是遍歷集合,然后調(diào)用put方法,將元素添加到集合中,所以也會(huì)拋出異常。
  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值相同鍵值對(duì)元素,并返回value值。如果沒找到就返回null。
  9. Set<K> keySet():創(chuàng)建一個(gè)Set集合,實(shí)現(xiàn)都是調(diào)用entrySet集合對(duì)應(yīng)方法。
    10.Collection<V> values():創(chuàng)建一個(gè)Collection集合,實(shí)現(xiàn)都是調(diào)用entrySet集合對(duì)應(yīng)方法。

AbstractMap的內(nèi)部類 SimpleEntry和SimpleImmutableEntry

都是實(shí)現(xiàn)了Map.Entry接口,表示一個(gè)簡(jiǎn)單地鍵值對(duì)類。它有兩個(gè)成員屬性key、value來存儲(chǔ)鍵值對(duì)。
唯一不同的是SimpleImmutableEntry表示一個(gè)不可修改鍵值對(duì)Entry類,,也就是說它的setValue(V value)方法會(huì)直接拋出異常。

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

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

  • java筆記第一天 == 和 equals ==比較的比較的是兩個(gè)變量的值是否相等,對(duì)于引用型變量表示的是兩個(gè)變量...
    jmychou閱讀 1,658評(píng)論 0 3
  • 一、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對(duì)于byte類型而言...
    龍貓小爺閱讀 4,476評(píng)論 0 16
  • title: java集合框架學(xué)習(xí)總結(jié) tags:集合框架 categories:總結(jié) date: 2017-03...
    行徑行閱讀 1,838評(píng)論 0 2
  • 今天我們分析一下集合框架的另一套體系,鍵值對(duì)的Map集合。Map集合是用鍵值對(duì)作為存儲(chǔ)元素的集合,所以它可以通過k...
    wo883721閱讀 445評(píng)論 0 0
  • 1 Map集合N016 1.1Map接口 【 ? 實(shí)現(xiàn)Map接口的集合類用來存儲(chǔ)"鍵-值"映射對(duì)。 ? JDK...
    征程_Journey閱讀 448評(píng)論 0 0

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