咱們一般說,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只能作有限的操做,限定哪些呢?一句話總結就是:只能讀,不能寫,但能刪能清。this
不信?咱們能夠看源碼。spa
首先來看values方法:code
public Collection<V> values() { Collection<V> vs = values; if (vs == null) { vs = new Values(); values = vs; } return vs; }
能夠看到values實際上是返回了一個Values類的,這是個內部類,就在它後面:blog
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,也是同樣的思路:rem
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 }