java中HashMap的keySet()和values()


    我們通常說,keySet()返回所有的鍵,values()返回所有的值,其實是不太對的,因為無論是keySet()和values(),其實都沒有實質的內容,且容我慢慢說來。

   他們前者返回了一個Set,后者返回了一個Collection,但是Set和Collection都只是接口,既然是接口,那就大有文章可以做。很重要的一點就是,接口可以不是new someClass()的來的,也就是說,它可以不對應與一個類,而只提供一些方法。實際上,HashMap中所有的數據都是放在一個Node<E,V>[]的數組中的,而返回的Set接口也好,Collection也罷,都是直接針對這個Node<E,V>[]數組的,所以,當使用返回的Set接口或者Collection接口進行操作是,實際上操作的還是那個Node<E,V>[]數組。但是,返回的Collection只能做有限的操作,限定哪些呢?一句話總結就是:只能讀,不能寫,但能刪能清。

不信?我們可以看源碼。

首先來看values方法:

public Collection<V> values() {
        Collection<V> vs = values;
        if (vs == null) {
            vs = new Values();
            values = vs;
        }
        return vs;
    }

可以看到values其實是返回了一個Values類的,這是個內部類,就在它后面:

    final class Values extends AbstractCollection<V> {
        public final int size()                 { return size; }
        public final void clear()               { HashMap.this.clear(); }
        public final Iterator<V> iterator()     { return new ValueIterator(); }
        public final boolean contains(Object o) { return containsValue(o); }
        public final Spliterator<V> spliterator() {
            return new ValueSpliterator<>(HashMap.this, 0, -1, 0, 0);
        }
        public final void forEach(Consumer<? super V> action) {
            Node<K,V>[] tab;
            if (action == null)
                throw new NullPointerException();
            if (size > 0 && (tab = table) != null) {
                int mc = modCount;
                for (int i = 0; i < tab.length; ++i) {
                    for (Node<K,V> e = tab[i]; e != null; e = e.next)
                        action.accept(e.value);
                }
                if (modCount != mc)
                    throw new ConcurrentModificationException();
            }
        }
    }

看到沒有,完全沒有提供新數據,完全是操作那個table,或者調用hashMap自己的方法。我之前傻呵呵的找源碼是怎么為values(HashMap除了有values這個方法,還有一個屬性也叫values,坑爹不?)賦值的,現在才知道自己是這么傻,因為根本就沒有復制嘛。

再來看keySet,也是一樣的思路:

 1     public Set<K> keySet() {
 2         Set<K> ks = keySet;
 3         if (ks == null) {
 4             ks = new KeySet();
 5             keySet = ks;
 6         }
 7         return ks;
 8     }
 9 
10     final class KeySet extends AbstractSet<K> {
11         public final int size()                 { return size; }
12         public final void clear()               { HashMap.this.clear(); }
13         public final Iterator<K> iterator()     { return new KeyIterator(); }
14         public final boolean contains(Object o) { return containsKey(o); }
15         public final boolean remove(Object key) {
16             return removeNode(hash(key), key, null, false, true) != null;
17         }
18         public final Spliterator<K> spliterator() {
19             return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
20         }
21         public final void forEach(Consumer<? super K> action) {
22             Node<K,V>[] tab;
23             if (action == null)
24                 throw new NullPointerException();
25             if (size > 0 && (tab = table) != null) {
26                 int mc = modCount;
27                 for (int i = 0; i < tab.length; ++i) {
28                     for (Node<K,V> e = tab[i]; e != null; e = e.next)
29                         action.accept(e.key);
30                 }
31                 if (modCount != mc)
32                     throw new ConcurrentModificationException();
33             }
34         }
35     }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM