繁体   English   中英

HashMap.keySet()如何返回键的视图?

[英]How can HashMap.keySet() return a view of keys?

这是java.util.HasMap类中的keySet()函数:

public Set<K> keySet() {
    Set<K> ks = keySet;
    if (ks == null) {
        ks = new KeySet();
        keySet = ks;
    }
    return ks;
}

在评论中,它说这个功能

返回此映射中包含的键的{@link Set}视图。 该集由地图支持,因此对地图的更改将反映在集中,反之亦然。

因此,我期望KeySet类型的对象,此函数返回的对象将包含对“视图键”的引用。 但是,当我查看代码时,KeySet类根本不包含任何字段及其所有超类。

final class KeySet extends AbstractSet<K> {
    public final int size()                 { return size; }
    public final void clear()               { HashMap.this.clear(); }
    public final Iterator<K> iterator()     { return new KeyIterator(); }
    public final boolean contains(Object o) { return containsKey(o); }
    public final boolean remove(Object key) {
        return removeNode(hash(key), key, null, false, true) != null;
    }
    public final Spliterator<K> spliterator() {
        return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
    }
    public final void forEach(Consumer<? super K> action) {
        Node<K,V>[] tab;
        if (action == null)
            throw new NullPointerException();
        if (size > 0 && (tab = table) != null) {
            int mc = modCount;
            for (int i = 0; i < tab.length; ++i) {
                for (Node<K,V> e = tab[i]; e != null; e = e.next)
                    action.accept(e.key);
            }
            if (modCount != mc)
                throw new ConcurrentModificationException();
        }
    }
}

有人可以解释一下

  1. “钥匙的视图”是什么意思? 什么样的数据是“观点”?
  2. HashMap.keySet()如何通过使用KeySet对象返回键的视图,该对象根本不包含对任何内容的任何引用?

为了更清楚:

这是打印出键集值的代码示例。 虽然KeySet对象保存对包含的地图数据的引用,但是如何准确地输出关键数据而不是地图的其他数据(不是值数据或其他任何数据)。 什么是告诉这个KeySet对象只保存MapKeys? 我在代码中看不到这样的指令。

package com.tutorialspoint;
import java.util.*;

public class HashMapDemo {
   public static void main(String args[]) {

     // create hash map
     HashMap newmap = new HashMap();

     // populate hash map
     newmap.put(1, "tutorials");
     newmap.put(2, "point");
     newmap.put(3, "is best");

     // get keyset value from map
     Set keyset = newmap.keySet();

     // check key set values
     System.out.println("Key set values are: " + keyset);
   }    
}

输出:

键集值为:[1,2,3]

  1. 视图 ”是一种对象,其数据由不同的对象支持,但以不同的方式提供。 在这种情况下,它提供Map的键的“视图”作为Set 这对用户和性能都有很多好处。

    值得注意的是,由于它与支持类共享其数据,因此内存开销非常小 - 它不需要将所有键复制到一个全新的Set 此外,用户无需担心视图与支持结构不同步 - 添加和删除将立即通过视图显示。

  2. 因为KeySet是一个内部类,所以它可以访问其包含类( HashMap )的实例的字段。 请注意代码段中的HashMap.this表示法。

    • size()return size; 是对HashMapsize字段的引用
    • clear()HashMap.this.clear(); 调用HashMapclear()方法(它需要使用HashMap.this来引用map的clear()方法而不是它自己的方法)
    • contains()代表HashMapcontainsKey()方法-这并不需要HashMap.this因为KeySet没有碰撞containsKey()方法
    • remove()类似地委托给HashMapremoveNode()

    如果它被声明为final static class KeySet那么它将是一个静态嵌套类,它不依赖于包含类的实例(它只是组织相关类的一种方式)。 在这种情况下, KeySet需要一个显式的HashMap字段,并且需要将有问题的地图传递给构造函数。 内部类使这隐含(这是简洁的,但有时令人困惑)。

  3. 什么是告诉这个KeySet对象只保存MapKeys?

    要明确的是,没有这样的指示。 KeySet实例可以传递地访问支持映射的所有字段和方法。 但是您的示例( System.out.println("Key set values are: " + keyset); keyset.toString() System.out.println("Key set values are: " + keyset); )隐式调用keyset.toString() ,这是(有意)未实现以返回映射的值。 因为KeySet扩展了AbstractSet (后者又扩展了AbstractCollection ),所以.toString()依赖于KeySetiterator()实现,该实现提供了映射键的迭代器,而不是其值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM