2019独角兽企业重金招聘Python工程师标准>>>
循环遍历一个 HashMap 可以通过下面的方式
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具体发生了哪些事情。
进入到这个 entrySet() 方法里面
public Set> entrySet() {
Set> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
final class EntrySet extends AbstractSet> {
public final int size() { return size; }
public final void clear() { HashMap.this.clear(); }
public final Iterator> iterator() {
return new EntryIterator();
}
...
}
如果是空的就new一个EntrtSet(),如果不是空的就直接返回,在看下EntrySet这个类,里面有一个 iterator() 方法,new一个EntryIterator()
final class EntryIterator extends HashIterator implements Iterator> {
public final Map.Entry next() { return nextNode(); }
}
abstract class HashIterator {
Node next; // next entry to return
Node current; // current entry
int expectedModCount; // for fast-fail
int index; // current slot
HashIterator() {
expectedModCount = modCount;
Node[] 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 nextNode() {
Node[] t;
Node 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 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 implements Map.Entry {
final int hash;
final K key;
V value;
Node next;
。。。
}
综上所述,用entrySet这种方式遍历一个map,其实就是获取到hashmap最底层的数组,从数组的第0个位置一直开始遍历,如果数组的位置是个链表,那么把链表也遍历一遍。回过头来看这个方法的名字 entrySet,hashmap的数组里面放的是Node,这个Node就是Map.Entry的实现类,entrySet 顾名思义就是所有 entry 的一个set集合。