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

Java HashMap.keySet()如何返回键的视图?,java,memory,hashmap,inner-classes,keyset,Java,Memory,Hashmap,Inner Classes,Keyset,下面是java.util.HasMap类中的keySet()函数: public Set<K> keySet() { Set<K> ks = keySet; if (ks == null) { ks = new KeySet(); keySet = ks; } return ks; } 输出: 键集值为:[1、2、3] “”是一种对象类型,其数据由不同的对象支持,但提供方式不同。在本例中,它提供了映射键的“

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

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

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

  • “”是一种对象类型,其数据由不同的对象支持,但提供方式不同。在本例中,它提供了
    映射
    键的“视图”,作为
    。这对用户和性能都有很多好处

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

  • 因为
    KeySet
    是一个类,所以它可以访问其包含类(
    HashMap
    )的实例的字段。注意
    HashMap。这是代码片段中的
    符号

    • size()
      返回大小
      是对
      HashMap
      size
      字段的引用
    • clear()
      HashMap.this.clear()
      调用
      HashMap
      clear()
      方法(它需要使用
      HashMap。这个
      引用映射的
      clear()
      方法,而不是它自己的方法)
    • contains()
      委托
      HashMap
      containsKey()
      方法-这不需要
      HashMap。这是因为
      KeySet
      没有冲突的
      containsKey()
      方法
    • remove()
    如果它被声明为
    final static class KeySet
    ,那么它将是一个静态嵌套类,它不绑定到包含类的实例(这只是组织相关类的一种方式)。在这种情况下,
    KeySet
    需要一个显式的
    HashMap
    字段,并且需要将有问题的映射传递到构造函数中。内部类使其隐式(这很简洁,但有时确实令人困惑)

  • 是什么告诉此KeySet对象仅保留MapKeys的

    明确地说,没有这样的指示。
    KeySet
    实例可传递地访问备份映射的所有字段和方法。但是,您的示例(
    System.out.println(“键集值为:“+keyset”);
    )隐式调用了
    keyset.toString()
    ,这(有意)不是为了返回映射的值而实现的。因为
    KeySet
    扩展了
    AbstractSet
    (这反过来又扩展了
    AbstractCollection
    ),所以它依赖于
    KeySet
    iterator()
    实现,该实现在映射的键上提供迭代器,而不是它的值


  • 谢谢你的回答。我仍然不理解“它提供了一个地图键的“视图”作为一个集合”的含义。你是说这里提到的“Set”将在包含HashMap键作为元素的内存中创建吗?如果不是,它来自何处?@Bonsaisteak这些关键元素只存储在
    HashMap
    中。
    键集
    不存储任何内容,它唯一的“字段”是对包含映射的隐式引用。
    KeySet
    的所有方法都使用此隐式引用来访问甚至修改映射的状态。@bonsai是的,
    Set
    反映了
    Map
    的内容(特别是其键)。它不复制或构造新对象-
    KeySet
    只需调用backing
    Map
    。例如,看看
    contains()
    ,它只是在映射上调用
    containsKey()
    HashMap)。这个
    可以省略,因为
    KeySet
    没有
    containsKey()
    方法)。@shmosel知道KeySet包含对包含映射的引用。然而,我仍然不明白是什么东西指定了它与包含地图键而不是其他数据的连接?@Bonsaisteak你能澄清你的问题吗(也许在编辑原始帖子时,这会给你更多的空间)
    KeySet
    只需作为一个内部类,就可以访问地图的所有数据。因为它的目的是显示有关地图键的信息,所以这就是类实际涉及的全部内容。在此处使用
    HashMap
    Set
    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();
            }
        }
    }
    
    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);
       }    
    }