keySet
中的密钥来自哪里?类KeySet
是HashMap
的内部类,它可以访问HashMap
变量,但没有像Set<K>
那样的直接变量,它只存储要引用的映射的键。
我只能找到一张Entry<K,V>[]
表格。但它存储了密钥和值
当调用new KeySet()
进行引用时,keySet()
方法会执行某些操作吗?可能类似于:
for(Entry e : table) {
keySet.put(e.getKey());
}
然后keySet存储的密钥,当添加或删除密钥值时,它也会添加或删除keySet
中的密钥?
public Set<K> keySet() {
Set<K> ks = keySet;
return (ks != null ? ks : (keySet = new KeySet()));
}
源代码只显示了一个new KeySet()
,但为什么它不是空的,而是有密钥?为了更清楚:
Map map = new HashMap();
map.put(1, 1); //null
map.keySet(); //[1]
map.put(2, 2); //[1,2]
map.remove(2); //[1]
在每一行调试和断点,检查每一行并观察映射的keySet变量会显示上面的结果,对吗?
一旦调用了keySet((,put和remove将对keySet产生相同的效果,对吗?我观察了HashMap的put和remove方法。
对于"put((",如果在调用"table[bucketIndex]=new Entry<>(hash,key,value,e(;"后调用addEntry->createEntry->,keySet将添加密钥
for调用table[i]=next之后的"remove(("->removeEntryForKey->;keySet中的键被删除了,所以我认为表[]和keySet之间一定有关联,然后我问了这个问题。。。
keySet()
返回由HashMap
支持的内部Set
实现。因此,例如,在该Set上调用contains(key)
会调用在后台HashMap
上的containsKey(key)
。
它不会创建一个独立的集合来保存原始HashMap
的键(正如您在代码片段中所建议的(,因为这样的Set
不会得到原始HashMap
的支持,所以HashMap
中的更改不会反映在Set
中,反之亦然。
以下是Java 6的实现:
/**
* Each of these fields are initialized to contain an instance of the
* appropriate view the first time this view is requested. The views are
* stateless, so there's no reason to create more than one of each.
*/
transient volatile Set<K> keySet = null;
public Set<K> keySet() {
Set<K> ks = keySet;
return (ks != null ? ks : (keySet = new KeySet()));
}
private final class KeySet extends AbstractSet<K> {
public Iterator<K> iterator() {
return newKeyIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsKey(o);
}
public boolean remove(Object o) {
return HashMap.this.removeEntryForKey(o) != null;
}
public void clear() {
HashMap.this.clear();
}
}
您可以浏览java.util.HashMap
的源代码来了解它是如何工作的。
keySet()
函数实际上返回HashMap
实例的一个成员变量,如下JDK源代码所示:
public Set<K> [More ...] keySet() {
Set<K> ks = keySet;
return (ks != null ? ks : (keySet = new KeySet()));
}
则keySet
是HashMap
的成员变量,其中它是本地定义的类:
private final class [More ...] KeySet extends AbstractSet<K> {
public Iterator<K> [More ...] iterator() {
return newKeyIterator();
}
public int [More ...] size() {
return size;
}
public boolean [More ...] contains(Object o) {
return containsKey(o);
}
public boolean [More ...] remove(Object o) {
return HashMap.this.removeEntryForKey(o) != null;
}
public void [More ...] clear() {
HashMap.this.clear();
}
}
因此,正如您所看到的,它只是为HashMap
中保存的相同数据定义了另一个"视图"。不会复制任何内容,因此可以保证keySet视图和原始贴图视图之间的一致性。
好的,我明白原因了。该方法确实返回了一个空的KeySet。但当它中断时,eclipse将调用方法AbstractCollection.toString((…然后调用KeySet.iterator((方法。