HashMap
迭代器非常容易理解,先看类关系图:
这三个迭代器,分别对应 entrySet
,keySet
和 values
方法返回对象的迭代器。这三个方法分别返回 EntrySet
,KeySet
和 Values
对象,这三个类均定义在 HashMap
中。
迭代器
迭代器的主要实现都在 HashIterator
这个抽象类中:
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;
// 初始化 next
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();
// 优先遍历箱,再遍历表
/*
* 这样的写法真的很有趣。简单两行,就完成了所想做的事,如果换成自己来写,没有十行代码是搞不
* 定的,不过 (next = (current = e).next) == null 这种在表达式中再去赋值,看起来
* 真的很不适应。
*/
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;
}
}
虽然 HashIterator
并没有直接实现 Iterator
接口,但其方法签名则完全是 Iterator
接口的(除了 nextNode
方法)。
下面再来看看,抽象类的具体实现:
final class KeyIterator extends HashIterator
implements Iterator<K> {
public final K next() { return nextNode().key; }
}
final class ValueIterator extends HashIterator
implements Iterator<V> {
public final V next() { return nextNode().value; }
}
final class EntryIterator extends HashIterator
implements Iterator<Map.Entry<K,V>> {
public final Map.Entry<K,V> next() { return nextNode(); }
}
实现非常简单,完全依赖迭代器的元素进行操作,具体实现都已经在 nextNode
方法中完成。
总结
迭代器的实现还是比较简单的。HashMap
本身并没有返回迭代器方法,而是在选择返回值或者 key 的方法时,重写了返回的 Set
对象或者 Collection
对象中的 Iterator
。
需要理解的是 HashMap
是如何去设计的,而且在源码中,发现大量在表达式中赋值的写法。这样的写法或许更简洁,至于可读性就智者见智了。
推荐博文
我与风来
认认真真学习,做思想的产出者,而不是文字的搬运工
错误之处,还望指出