keySet
中的密钥来自哪里?
类KeySet
是HashMap
的内部类,它可以访问HashMap
个变量,但没有像Set<K>
这样的直接变量,它只存储地图的键参考。
我只能找到Entry<K,V>[]
表。但它存储了关键和价值
keySet()
方法在调用new 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()”,如果调用addEntry - &gt; createEntry - &gt;在调用“table [bucketIndex] = new Entry&lt;&gt;(hash,key,value,e)之后;” keySet将添加密钥
代表“remove()” - &gt; removeEntryForKey - &gt;在调用table [i] = next之后; keySet中的键被删除了,所以我认为table []和keySet之间必定有一些关联,然后我问了这个问题......
答案 0 :(得分:1)
keySet()
返回由Set
支持的内部HashMap
实施。因此,例如,在该集合上调用contains(key)
会在后备containsKey(key)
上调用HashMap
。
它不会创建一个独立的Set,其中包含原始HashMap
的密钥(正如您在代码段中所建议的那样),因为这样的Set
不会被原始HashMap
支持1}},因此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();
}
}
答案 1 :(得分:0)
您可以浏览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视图与原始地图视图之间的一致性。
答案 2 :(得分:0)
好吧,我明白了。该方法确实返回一个空的KeySet。但是当它中断时,eclipse将调用方法AbstractCollection.toString()...然后调用KeySet.iterator()方法。