-5

里面的钥匙keySet从哪里来?该类KeySet是 的内部类HashMap,它可以访问HashMap变量,但没有像 aSet<K>这样的直接变量,它只存储要引用的映射键。

我只能找到一张Entry<K,V>[]桌子。但它已经存储了键和值。当调用该方法进行引用时
,该方法是否会keySet()执行某些操作?new KeySet()可能是这样的:

for(Entry e : table) {
    keySet.put(e.getKey());
}

那么keySet存储的keys,当添加或删除一个key-value时,它也会添加或删除keySet相同的keys吗?

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]

在每一行调试和断点,检查每一行并观察 map 的 keySet 变量会显示上面的结果,对吗?

一旦 keySet() 被调用,put 和 remove 对 keySet 的效果是一样的,对吧?我已经查看了 HashMap 的 put 和 remove 方法。

对于“put()”,如果调用 addEntry -> createEntry -> 在调用“table[bucketIndex] = new Entry<>(hash, key, value, e);”之后 keySet 将添加密钥,

for "remove()" ->removeEntryForKey -> 调用 table[i] = next; keySet中的key被删除了,所以我认为table[]和keySet之间一定有某种关联,然后我问了这个问题......

4

3 回答 3

1

keySet()返回SetHashMap. 因此,例如,调用contains(key)该 Set 调用containsKey(key)backing HashMap

它不会创建一个独立的 Set 来保存原始的键HashMap(正如您在代码片段中所建议的那样),因为这样的 aSet不会由 original 支持HashMap,因此在 the 中的更改HashMap不会反映在 the 中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();
    }
}
于 2015-08-04T08:07:28.873 回答
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 视图和原始地图视图之间的一致性。

于 2015-08-04T08:11:53.433 回答
0

好的,我明白了。该方法确实返回一个空的 KeySet。但是当它中断时。eclipse 将调用方法 AbstractCollection.toString()...然后调用 KeySet.iterator() 方法。

于 2015-08-05T00:51:09.653 回答