简体   繁体   English

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

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

Here is the keySet() function inside java.util.HasMap class : 这是java.util.HasMap类中的keySet()函数:

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

In the comment, it says this function 在评论中,它说这个功能

Returns a {@link Set} view of the keys contained in this map. 返回此映射中包含的键的{@link Set}视图。 The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. 该集由地图支持,因此对地图的更改将反映在集中,反之亦然。

Therefore, I expected the object of KeySet type, which this functions returns would contain a reference to the "view of keys". 因此,我期望KeySet类型的对象,此函数返回的对象将包含对“视图键”的引用。 However when I look at the code, the KeySet class does not contain any field at all, and all of its super classes either. 但是,当我查看代码时,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();
        }
    }
}

Could somebody please explain 有人可以解释一下

  1. What does "a view of the keys" mean? “钥匙的视图”是什么意思? What kind of data is "a view"? 什么样的数据是“观点”?
  2. How can the HashMap.keySet() returns a view of the keys by using KeySet object, which doesn't contain any reference to anything at all? HashMap.keySet()如何通过使用KeySet对象返回键的视图,该对象根本不包含对任何内容的任何引用?

To make it more clear : 为了更清楚:

Here is a code sample to print out the keyset value. 这是打印出键集值的代码示例。 Although the KeySet object holds the reference to the containing map data, how can this exactly output the key data but not other data of the map (not value data or anything else). 虽然KeySet对象保存对包含的地图数据的引用,但是如何准确地输出关键数据而不是地图的其他数据(不是值数据或其他任何数据)。 What is the thing that tells this KeySet object to hold only MapKeys? 什么是告诉这个KeySet对象只保存MapKeys? I can't see such instruction in its code. 我在代码中看不到这样的指令。

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);
   }    
}

Ouput : 输出:

Key set values are: [1, 2, 3] 键集值为:[1,2,3]

  1. A " view " is a type of object whose data is backed by a different object, but is provided in a different way. 视图 ”是一种对象,其数据由不同的对象支持,但以不同的方式提供。 In this case, it's providing a "view" of the Map 's keys as a Set . 在这种情况下,它提供Map的键的“视图”作为Set This has a number of benefits, both for users and for performance. 这对用户和性能都有很多好处。

    Notably, since it shares its data with the backing class there's very little memory overhead - it doesn't need to copy all the keys into a whole new Set . 值得注意的是,由于它与支持类共享其数据,因此内存开销非常小 - 它不需要将所有键复制到一个全新的Set Additionally, users don't need to worry about the view getting out of sync with the backing structure - additions and removals will be visible via the view immediately. 此外,用户无需担心视图与支持结构不同步 - 添加和删除将立即通过视图显示。

  2. Because KeySet is an inner class it has access to the fields of an instance of its containing class ( HashMap ). 因为KeySet是一个内部类,所以它可以访问其包含类( HashMap )的实例的字段。 Notice the HashMap.this notation in your code snippet. 请注意代码段中的HashMap.this表示法。

    • size() 's return size; size()return size; is a reference to HashMap 's size field 是对HashMapsize字段的引用
    • clear() 's HashMap.this.clear(); clear()HashMap.this.clear(); calls HashMap 's clear() method (it needs to use HashMap.this to reference the map's clear() method rather than its own) 调用HashMapclear()方法(它需要使用HashMap.this来引用map的clear()方法而不是它自己的方法)
    • contains() delegates HashMap 's containsKey() method - this doesn't require HashMap.this because KeySet doesn't have a colliding containsKey() method contains()代表HashMapcontainsKey()方法-这并不需要HashMap.this因为KeySet没有碰撞containsKey()方法
    • remove() similarly delegates to HashMap 's removeNode() remove()类似地委托给HashMapremoveNode()

    If it was instead declared as final static class KeySet it would be a static nested class, which is not tied to an instance of the containing class (it's just a way of organizing related classes). 如果它被声明为final static class KeySet那么它将是一个静态嵌套类,它不依赖于包含类的实例(它只是组织相关类的一种方式)。 In that case KeySet would need an explicit HashMap field, and the map in question would need to be passed into the constructor. 在这种情况下, KeySet需要一个显式的HashMap字段,并且需要将有问题的地图传递给构造函数。 Inner classes make this implicit (which is concise, but certainly sometimes confusing). 内部类使这隐含(这是简洁的,但有时令人困惑)。

  3. What is the thing that tells this KeySet object to hold only MapKeys? 什么是告诉这个KeySet对象只保存MapKeys?

    To be clear, there is no such instruction. 要明确的是,没有这样的指示。 A KeySet instance transitively has access to all the fields and methods of the backing map. KeySet实例可以传递地访问支持映射的所有字段和方法。 However your example ( System.out.println("Key set values are: " + keyset); ) is implicitly calling keyset.toString() , which is (intentionally) not implemented to return the map's values. 但是您的示例( System.out.println("Key set values are: " + keyset); keyset.toString() System.out.println("Key set values are: " + keyset); )隐式调用keyset.toString() ,这是(有意)未实现以返回映射的值。 Because KeySet extends AbstractSet (which in turn extends AbstractCollection ) its .toString() relies on the KeySet 's iterator() implementation, which provides an iterator over the map's keys, not its values. 因为KeySet扩展了AbstractSet (后者又扩展了AbstractCollection ),所以.toString()依赖于KeySetiterator()实现,该实现提供了映射键的迭代器,而不是其值。

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

相关问题 hashmap.keyset()会按照它们添加到hashmap的顺序返回键吗? - Will hashmap.keyset() return keys in the order they were added to the hashmap? HashMap.values()和HashMap.keySet()如何返回值和键? - How do HashMap.values() and HashMap.keySet() return values and keys? HashMap.KeySet()在Java 7中以不同顺序返回键Java 8 - HashMap.KeySet() returns keys in different order in Java 7 Java 8 将HashMap.keySet()转换为CharSequence []? - Convert HashMap.keySet() to CharSequence[]? Hashmap.keySet(),foreach和remove - Hashmap.keySet(), foreach, and remove HashMap.values()/ HashMap.keySet()何时按引用返回,何时按值返回? - When Does HashMap.values()/HashMap.keySet() Return By Reference And When Does It Return By Value? 使用HashMap.keySet作为脏副本 - Using HashMap.keySet as a dirty copy 如何从Java Rest服务在引导表中显示Java Hashmap.keySet()? - How to display Java Hashmap.keySet() in a bootstrap table, from a java rest service? 如何使用keySet()。iterator()在HashMap中的键中查找模式 - How to use keySet().iterator() to find patterns in keys in a HashMap 是什么导致java.util.HashSet和HashMap.keySet()类的iterator()稍微不可预测的排序? - What causes the slightly unpredictable ordering of the iterator() for the java.util.HashSet and HashMap.keySet() classes?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM