Java集合--HashIterator

循环遍历一个 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<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集合。

 

 

 

转载于:https://my.oschina.net/u/232911/blog/2870182

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值