HashMap.entrySet( )分析

我们在写代码的时候经常会用到HashMap这个方法的entrySet()方法,这个方法返回返回的是一个Set对象,很多人以为返回的是一个包含了Map里面所有键值对的一个集合对象,这个理解不准确,怎么说呢,通过这个Set对象,我们确实可以获取到Map里面存放的所有键值对,但是这个集合对象本身是不存放数据的,它只是助于我们遍历Map中的数据,类似于Iterator。下面我们来看看源码简要分析一下。

public Set<Map.Entry<K,V>> entrySet() {
    Set<Map.Entry<K,V>> es;
    return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}

上面是entrySet()的源码,我么可以知道返回的其实是HashMap内部维护的一个引用entrySet,这个应用是EntrySet类型的。我们本能在HashMap的源码中找一下entrySet是何时填充数据的,搜遍代码我们会发现没有该逻辑,这个很奇怪啊,我们来看一下EntrySet的类定义,该类定义在HashMap的内部:

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();
    }
    public final boolean contains(Object o) {
        if (!(o instanceof Map.Entry))
            return false;
        Map.Entry<?,?> e = (Map.Entry<?,?>) o;
        Object key = e.getKey();
        Node<K,V> candidate = getNode(hash(key), key);
        return candidate != null && candidate.equals(e);
    }
    public final boolean remove(Object o) {
        if (o instanceof Map.Entry) {
            Map.Entry<?,?> e = (Map.Entry<?,?>) o;
            Object key = e.getKey();
            Object value = e.getValue();
            return removeNode(hash(key), key, value, true, true) != null;
        }
        return false;
    }
    public final Spliterator<Map.Entry<K,V>> spliterator() {
        return new EntrySpliterator<>(HashMap.this, 0, -1, 0, 0);
    }
    public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
        Node<K,V>[] tab;
        if (action == null)
            throw new NullPointerException();
        if (size > 0 && (tab = table) != null) {
            int mc = modCount;
            // Android-changed: Detect changes to modCount early.
            for (int i = 0; (i < tab.length && modCount == mc); ++i) {
                for (Node<K,V> e = tab[i]; e != null; e = e.next)
                    action.accept(e);
            }
            if (modCount != mc)
                throw new ConcurrentModificationException();
        }
    }
}

我们重点看一下EntrySet的forEach方法,可以看出这个方法可以读取到其所在的HashMap对象的存储的所有键值对,而我们经常使用entrySet方法就是用来进行foreach循环的。

好了,HashMap.entrySet( )本身并没有难度,但是有些朋友可能会对这个api理解并不准确,记住,该方法并不是返回一个存储数据的集合,它只是一个视图窗口。HashMap.ketSet()原理类似。

 

 

    原文作者:Android海纳百川
    原文地址: https://blog.csdn.net/baidu_27196493/article/details/88379318
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞