續前一篇java容器源碼分析(四)——HashMap,繼續分析HashMap的源碼。java
containsValue(Object value):
數組
public boolean containsValue(Object value) { if (value == null) return containsNullValue(); Entry[] tab = table; for (int i = 0; i < tab.length ; i++) for (Entry e = tab[i] ; e != null ; e = e.next) if (value.equals(e.value)) return true; return false; }
能夠看出,這裏對table作了一次線性遍歷纔可以獲取出value,複雜度爲O(n)。app
再看一下Map遍歷用到的方法entrySet()
函數
public Set<Map.Entry<K,V>> entrySet() { return entrySet0(); } private Set<Map.Entry<K,V>> entrySet0() { Set<Map.Entry<K,V>> es = entrySet; return es != null ? es : (entrySet = new EntrySet()); }
entrySet調用了entrySet0,entrySet0返回了EntrySet對象,有點重複的樣子!源碼分析
看來主要的內容在EntrySet中,EntrySet是一個內部類。ui
private final class EntrySet extends AbstractSet<Map.Entry<K,V>> { public Iterator<Map.Entry<K,V>> iterator() { return newEntryIterator(); } public boolean contains(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<K,V> e = (Map.Entry<K,V>) o; Entry<K,V> candidate = getEntry(e.getKey()); return candidate != null && candidate.equals(e); } public boolean remove(Object o) { return removeMapping(o) != null; } public int size() { return size; } public void clear() { HashMap.this.clear(); } }
並無什麼屬性!其實它是一個代理類,而且由於它是HashMap的內部類,因此能夠直接調用HashMap的方法、屬性。這個set並無add方法。EntrySet的迭代器,是經過newEntryIterator返回。this
Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); }
繼續往下看:設計
private final class EntryIterator extends HashIterator<Map.Entry<K,V>> { public Map.Entry<K,V> next() { return nextEntry(); } }
EntryIterator是繼承了HashIterator類。代理
private abstract class HashIterator<E> implements Iterator<E>
HashIterator是HashMap的內部抽象類,實現了Iterator接口。code
其構造函數
HashIterator() { expectedModCount = modCount; if (size > 0) { // advance to first entry Entry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } }
遍歷table數組,找到第一個不爲空的槽。
hasNext方法
public final boolean hasNext() { return next != null; }
若是next不爲空,則存在下一個元素。
public void remove() { if (current == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); Object k = current.key; current = null; HashMap.this.removeEntryForKey(k); expectedModCount = modCount; }
remove方法是調用了HashMap的removeEntryForKey方法。沒看到next方法,這是由於HashMap想複用HashIteraotr這個類,咱們看到HashMap有三個迭代器:
private final class ValueIterator extends HashIterator<V> { public V next() { return nextEntry().value; } } private final class KeyIterator extends HashIterator<K> { public K next() { return nextEntry().getKey(); } } private final class EntryIterator extends HashIterator<Map.Entry<K,V>> { public Map.Entry<K,V> next() { return nextEntry(); } }
ValueIterator是給values()用的迭代器,KeyIterator是給KeySet用的迭代器,EntryIterator是提供給EntrySet使用的迭代器。
這裏有能夠看出一個很是常見的設計:接口實現規範,抽象類實現大部分工做,具體類實現差別化內容!
看下HashIterator的nextEntry方法
final Entry<K,V> nextEntry() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); Entry<K,V> e = next; if (e == null) throw new NoSuchElementException(); if ((next = e.next) == null) { Entry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } current = e; return e; }
對table一個槽一個槽的鏈表遍歷。
在看下keySet()方法
public Set<K> keySet() { Set<K> ks = keySet; return (ks != null ? ks : (keySet = new KeySet())); } private final class KeySet extends AbstractSet<K> { public Iterator<K> iterator() { return newKeyIterator(); } public int size() { return size; } public boolean contains(Object o) { return containsKey(o); } public boolean remove(Object o) { return HashMap.this.removeEntryForKey(o) != null; } public void clear() { HashMap.this.clear(); } }
額,和EntrySet基本同樣。繼續看Values()
public Collection<V> values() { Collection<V> vs = values; return (vs != null ? vs : (values = new Values())); } private final class Values extends AbstractCollection<V> { public Iterator<V> iterator() { return newValueIterator(); } public int size() { return size; } public boolean contains(Object o) { return containsValue(o); } public void clear() { HashMap.this.clear(); } }
仍是差很少。
從分析Iterator的實現中能夠看到,iterator是要遍歷整個table的,因此不要將capacity的值設置得過高,也不要把loadfactor的值設置得過低。看HashMap的這句註釋:
Iteration over collection views requires time proportional to the "capacity" of the HashMap instance (the number of buckets) plus its size (the number of key-value mappings). Thus, it's very important not to set the initial capacity too high (or the load factor too low) if iteration performance is important.
HashMap的分析到這裏也差很少了,對於HashMap,仍是對其hash方法不太明白。