Java集合--HashIterator

循環遍歷一個 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

相關文章
相關標籤/搜索