无法理解entrySet()方法

时间:2017-07-28 08:47:03

标签: java hashmap

我们可以使用entrySet()方法迭代存储在Node []表字段中的hashmap键值对。

HahMap<K,V> hashmap = new HashMap<>() ;

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

当我们在for-each循环中使用它时,如:

for ( Map.Entry<K,V> entry : hashmap.entrySet () ) 
{
... 
// entry is an object of return type Map.Entry and object type Node . 
// got the object type by calling entry.getClass() and also no other inner class other than Node implements Map.Entry .   ; 

} 

这些对象存储在Set中。但是将代码链接到具有键值对的字段表的代码在哪里。

例如: 在toString()方法中,当我们使用iterator()方法获取Iterable,并在Iterable上调用next()方法时,调用转到HashIterator类的nextNode(),其中返回的对象链接到HashMap类的表字段。 但这里发生了什么?请帮忙 。

2 个答案:

答案 0 :(得分:1)

您似乎缺乏对视图的理解。 视图没有存储的数据,只是通过委托给实际的数据对象来完成某个接口。

一个简单的例子是通过Collections.unmodifiableList(…)创建的列表 view ,它不包含任何数据,但当然将所有方法调用委托给原始列表,不包括修改方法。 / p>

通过委托给底层地图,条目集满足Set接口。最值得注意的是,通过返回Iterator,因为大多数方法都建立在此基础之上,只有少数其他方法被覆盖以提高性能,例如: size()直接委托地图size()。因此,如果看起来好像条目集包含某些内容,那么它就是因为迭代器在遍历期间报告它。

Hashmap的条目集迭代器遍历条目的内部数组,就像键集迭代器和值集合迭代器一样。它们之间唯一的区别是它们在next()方法中返回的对象,条目集迭代器只返回条目,另外两个提取密钥resp。条目的价值。这就是为什么这些迭代器只覆盖那个单一的方法。

请注意,这种互动也可以反过来看。通过扩展AbstractMap来实施Map时,entrySet()是您需要实现的唯一方法,所有其他地图方法都已通过委派方式实施入门集。但是,您可以覆盖其中一些以提高性能。但实际上包含数据的问题没有实际意义,Map和条目Set都是对相同基础数据的视图。

以下示例可能会有所帮助:

String[][] pairs={ {"foo","bar"}, {"hello","world"} };

Map<String,String> map = new AbstractMap<String, String>() {
    public Set<Map.Entry<String, String>> entrySet() {
        return new AbstractSet<Entry<String, String>>() {
            public Iterator<Map.Entry<String, String>> iterator() {
                return Arrays.stream(pairs)
                    .<Entry<String,String>>map(p -> new SimpleImmutableEntry<>(p[0],p[1]))
                    .iterator();
            }
            public int size() {
                return pairs.length;
            }
        };
    }
};

System.out.println(map.get("foo"));
System.out.println(map.containsKey("hello"));
System.out.println(map.containsValue("world"));
map.forEach((k,v) -> System.out.println(k+" -> "+v));
System.out.println(map);

它创建了一个永不放入的不可变映射。它仍然通过所有Map方法报告预期内容,只是因为条目集迭代器报告了这些内容。

答案 1 :(得分:0)

如果我没有遗漏您的问题中的任何内容:EntrySet会覆盖iterator方法(将其设为Iterable以便在forEach中使用),然后返回EntryIterator - 它会覆盖next方法:

public final Map.Entry<K,V> next() { return nextNode(); }

但它也扩展了定义HashIterator方法的hasNext

实际上就是这么简单。但通常这些是内部类 - 他们可以访问HashMap类中可能需要的所有内容。