循環遍歷一個 HashMap 能夠經過下面的方式java
for (Map.Entry entry : hashMap.entrySet()) { Object key = entry.getKey(); Object value = entry.getValue(); .... }
或者用迭代器數組
Iterator iterator = hashMap.entrySet().iterator(); while (iterator.hasNext()) { Object object = iterator.next(); .... }
實際上是同樣的 foreach 底層就是調用了 iterator.next() 方法。源碼分析
下面經過源碼分析一下究竟如何遍歷一個map和遍歷一個map具體發生了哪些事情。this
進入到這個 entrySet() 方法裏面code
public Set<Map.Entry<K,V>> entrySet() { Set<Map.Entry<K,V>> es; return (es = entrySet) == null ? (entrySet = new EntrySet()) : es; } final class EntrySet extends AbstractSet<Map.Entry<K,V>> { public final int size() { return size; } public final void clear() { HashMap.this.clear(); } public final Iterator<Map.Entry<K,V>> iterator() { return new EntryIterator(); } ... }
若是是空的就new一個EntrtSet(),若是不是空的就直接返回,在看下EntrySet這個類,裏面有一個 iterator() 方法,new一個EntryIterator()繼承
final class EntryIterator extends HashIterator implements Iterator<Map.Entry<K,V>> { public final Map.Entry<K,V> next() { return nextNode(); } } abstract class HashIterator { Node<K,V> next; // next entry to return Node<K,V> current; // current entry int expectedModCount; // for fast-fail int index; // current slot HashIterator() { expectedModCount = modCount; Node<K,V>[] t = table; current = next = null; index = 0; if (t != null && size > 0) { // advance to first entry do {} while (index < t.length && (next = t[index++]) == null); } } public final boolean hasNext() { return next != null; } final Node<K,V> nextNode() { Node<K,V>[] t; Node<K,V> e = next; if (modCount != expectedModCount) throw new ConcurrentModificationException(); if (e == null) throw new NoSuchElementException(); if ((next = (current = e).next) == null && (t = table) != null) { do {} while (index < t.length && (next = t[index++]) == null); } return e; } public final void remove() { Node<K,V> p = current; if (p == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); current = null; K key = p.key; removeNode(hash(key), key, null, false, false); expectedModCount = modCount; } }
這個 EntryIterator 繼承自 HashIterator 實現了 Iterator 接口,這裏的 next() 方法直接調用的是HashIterator類的 nextNode() 方法,從這能夠看出來這個next方法其實返回的就是 Node 節點的 next 字段。Node節點是這樣的接口
static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; V value; Node<K,V> next; 。。。 }
綜上所述,用entrySet這種方式遍歷一個map,其實就是獲取到hashmap最底層的數組,從數組的第0個位置一直開始遍歷,若是數組的位置是個鏈表,那麼把鏈表也遍歷一遍。回過頭來看這個方法的名字 entrySet,hashmap的數組裏面放的是Node,這個Node就是Map.Entry的實現類,entrySet 顧名思義就是全部 entry 的一個set集合。rem