这是java.util.HasMap类中的keySet()函数:
@JvmStatic
在评论中,它说明了此功能
返回此映射中包含的键的{@link Set}视图。 该集受地图支持,因此对地图的更改是 反映在集合中,反之亦然。
因此,我希望此函数返回的KeySet类型的对象将包含对“键视图”的引用。 但是,当我查看代码时,KeySet类根本不包含任何字段,也不包含其所有超类。
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new KeySet();
keySet = ks;
}
return ks;
}
有人可以解释
为了更加清楚:
这是一个代码示例,用于打印出键集值。尽管KeySet对象保留了对包含的地图数据的引用,但是如何才能准确地输出键数据而不是地图的其他数据(不是值数据或其他任何数据)。告诉此KeySet对象仅保留MapKeys的东西是什么?我在其代码中看不到这样的指令。
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();
}
}
}
输出:
键设置值是:[1、2、3]
答案 0 :(得分:8)
“ view”是一种对象,其数据由其他对象支持,但是以不同的方式提供。在这种情况下,它将Map
的键的“视图”作为Set
提供。这对于用户和性能都有很多好处。
值得注意的是,由于它与后备类共享数据,因此内存开销很小-它不需要将所有密钥复制到全新的Set
中。此外,用户无需担心视图与支持结构不同步-添加和删除将立即通过视图可见。
由于KeySet
是inner class,因此可以访问其包含类(HashMap
)的实例的字段。请注意代码段中的HashMap.this
表示法。
size()
的{{1}}是对return size;
的{{1}}字段的引用HashMap
的{{1}}调用size
的{{1}}方法(它需要使用clear()
来引用地图的HashMap.this.clear();
方法比它自己的)HashMap
代表clear()
的{{1}}方法-这不需要HashMap.this
,因为clear()
没有冲突的contains()
方法HashMap
类似地委托给containsKey()
的{{1}} 如果改为声明为HashMap.this
,则它将是一个静态嵌套类,它不与包含类的实例绑定(这只是组织相关类的一种方式)。在那种情况下,KeySet
将需要一个显式的containsKey()
字段,并且所涉及的映射将需要传递到构造函数中。内部类使此隐式(简明扼要,但有时有时会令人困惑)。
告诉此KeySet对象仅保留MapKeys是什么?
为清楚起见,没有此类说明。 remove()
实例可传递地访问支持映射的所有字段和方法。但是,您的示例(HashMap
)隐式调用removeNode()
,(有意地)未实现该操作以返回映射的值。由于final static class KeySet
扩展了KeySet
(又扩展了HashMap
),因此其.toString()
依赖于KeySet
的{{1}}实现,该实现提供了迭代器而不是地图的值。