[英]When Does HashMap.values()/HashMap.keySet() Return By Reference And When Does It Return By Value?
[英]How do HashMap.values() and HashMap.keySet() return values and keys?
HashMap.values()
的源代码如下所示
public Collection<V> values() {
Collection<V> vs = values;
return (vs != null ? vs : (values = new Values()));
}
如您所见,当values()
方法首次调用时,它只返回一个Values
对象。 Values
对象是AbstractCollection
的子类,没有构造函数,当然不包含任何元素。 但是当我调用该方法时,它会快速返回一个集合
Collection<String> values = map.values();
System.out.println(values);
那太奇怪了。 不仅values()
,而且keySet()
和entrySet()
方法返回这样的空对象。 那么,这是我的问题,这些方法何时以及如何返回具有我们需要的元素的对象?
错误的观点是, Values
类“当然是空的”。 只是因为没有调用它的方法并且它的构造函数没有任何参数并不意味着该集合是空的。
Values
类是HashMap
的“内部类”(非静态嵌套类 ),这意味着它具有对创建它的HashMap
对象的隐式引用。 因此,它可以通过使用HashMap.this
引用或直接访问成员来显式访问HashMap
所有元素。 由于它是一个内部类,甚至允许访问HashMap
的私有成员。
您可以在Values
类的size
方法实现中看到:
public int size() {
return size;
}
Values
类没有size
成员,因此size
指的是HashMap
的大小。 它相当于:
public int size() {
return HashMap.this.size;
}
编辑:请注意,这也意味着您收到的集合不是副本,但仍然引用原始的HashMap
内容,因此在更新HashMap
时会更改:
// Getting the entry set (not a copy!)
Set<Entry<String, String>> entries = map.entrySet();
// Add elements to the map afterwards
map.put("abc", "def");
// Check out the entries in the collection
// (magically containing the elements added after getting the collection)
System.out.println(entries); // "[abc=def]"
Values
类实现了由HashMap
支持的Collection
。 正如mastov所评论的, Values
是HashMap
的内部类,它允许访问与之关联的封闭HashMap
实例的成员。 因此它不是空的。 它的大小是HashMap
的大小,当你迭代它时,你正在迭代HashMap
的条目。
当你调用System.out.println(values);
,您正在调用AbstractCollection
的toString
方法,该方法使用Iterator
迭代值并获取其String
表示形式。 Iterator
实际上遍历HashMap
的条目并返回它们的值。
对于keySet
和entrySet
返回的Set
,情况也是如此。
Collection<V> vs = values;
return (vs != null ? vs : (values = new Values()));
这两行回答了你的问题。
values
是一个内部集合(从AbstractMap
继承)。 如果它不为null
则返回它。
如果它为null
则它将被初始化并返回新的。
现在我想,你的问题的主要观点是
何时以及如何使用我们需要的元素返回对象?
技术上, values
始终返回此初始化对象。 那么我们如何从这些对象中获取入口值。
让我们走得更远:
values()实际上返回类Values
的对象,它是HashMap
的Inner类,并扩展了AbstractCollection
private final class Values extends AbstractCollection<V>
正如您已查看源代码。 然后你会在Values
类中找到它
public Iterator<V> iterator() {
return newValueIterator();
}
这个newValueIterator()
可以解决问题。
如果你更深入,你会发现newValueIterator()
返回ValueIterator
对象,它是HashIterator
的子类HashIterator
实现迭代的基本功能,它实际上是在HashMap
维护的table
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.