java - 无法理解entrySet()方法

标签 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 类的表字段。 但这里会发生什么?请帮忙 。

最佳答案

您似乎缺乏对 View 是什么的理解。 View 没有存储数据,只是通过委托(delegate)给实际数据对象来实现某个接口(interface)。

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

条目集通过委托(delegate)给底层映射来实现Set接口(interface)。最值得注意的是,通过返回一个迭代器,因为大多数方法都是在此基础上构建的,所以只有少数其他方法会为了性能而被重写,例如size() 直接委托(delegate)给 map 的 size()。因此,如果条目集看起来好像包含某些内容,那么它确实包含某些内容,因为迭代器在遍历期间报告了它。

Hashmap 的条目集迭代器迭代内部条目数组,就像键集迭代器和值集合迭代器一样。它们之间的唯一区别在于它们在 next() 方法中返回哪个对象,条目集迭代器仅返回条目,其他两个分别提取键。条目的值。这就是为什么这些迭代器只重写单个方法。

请注意,这种交互也可以反过来看。当您通过扩展 AbstractMap 实现 Map 时,entrySet() 是您需要实现的唯一方法,所有其他映射方法都已通过对条目集的委托(delegate)来实现。不过,您可能会为了性能而覆盖其中一些。但实际上包含数据的问题是没有意义的,Map 和条目 Set 都是相同底层数据的 View 。

也许下面的例子有帮助:

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 方法报告了预期的内容,只是因为条目集迭代器报告了此内容。

关于java - 无法理解entrySet()方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45368913/

相关文章:

java - 如何访问抽象类的 Hashmap?

java - 要洗牌的键值(整数,字符串)列表的最佳结构

java - ArrayList.contains() 对比 HashMap.containsKey() 对比 HashMap.get()

java - 实现 N 个常量之间链接的最佳方式

java - OpenJpa 查询缓存在空值的情况下不刷新

java - 通过jprofile分析内存中所有垃圾

java - Tomcat 不刷新响应缓冲区

java - 一旦执行异步任务任务,变量就会丢失数据

java.util.IllegalFormatConversionException异常

java - 在java中合并相似的HashMaps