问题
I have a query regarding iterator of HashSet in Java. In book "Java Generics and Collections", following is stated:
The chief attraction of a hash table implementation for sets is the (ideally) constanttime performance for the basic operations of add, remove, contains, and size. Its main disadvantage is its iteration performance; since iterating through the table involves examining every bucket, its cost is proportional to the table size regardless of the size of the set it contains.
It states that iterator looks in every bucket of underlying table. But going through actual implementation(JDK 8), I see that HashIterator stores next node reference. So it seems iterator doesn't need to visit every single bucket.
Is book wrong here OR my understanding is wrong?
回答1:
The document is right. Although KeyIterator
indeed calls nextNode().key
, like this
final class KeyIterator extends HashIterator implements Iterator<K> {
public final K More ...next() {
return nextNode().key;
}
}
the code for nextNode()
in the base class HashIterator
has the loop that the documentation is talking about:
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;
}
The do
/while
loop with an empty body traverses the buckets one by one, looking for the next entry.
The only time this may be relevant is when you iterate over a hash set which you pre-allocated with a large number of buckets, but have not populated with a large number of items yet. When you let your HashSet
grow by itself as you add more items, the number of buckets will be proportional to the number of items that you inserted so far, so the slowdown would not be significant.
来源:https://stackoverflow.com/questions/32035709/hashset-iteration