[英]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 有人可以解释一下
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]
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. 此外,用户无需担心视图与支持结构不同步 - 添加和删除将立即通过视图显示。
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 HashMap
的size
字段的引用 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) HashMap
的clear()
方法(它需要使用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()
代表HashMap
的containsKey()
方法-这并不需要HashMap.this
因为KeySet
没有碰撞containsKey()
方法 remove()
similarly delegates to HashMap
's removeNode()
remove()
类似地委托给HashMap
的removeNode()
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). 内部类使这隐含(这是简洁的,但有时令人困惑)。
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()
依赖于KeySet
的iterator()
实现,该实现提供了映射键的迭代器,而不是其值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.