续前一篇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方法不太明白。