源代码HashMap.values()如下所示
public Collection<V> values() {
Collection<V> vs = values;
return (vs != null ? vs : (values = new Values()));
}
Run Code Online (Sandbox Code Playgroud)
如您所见,当values()首次调用该方法时,它只返回一个Values对象.该Values对象是AbstractCollection没有构造函数的子类,当然不包含任何元素.但是当我调用该方法时,它会快速返回一个集合
Collection<String> values = map.values();
System.out.println(values);
Run Code Online (Sandbox Code Playgroud)
那太奇怪了.不仅values(),而且还keySet()和entrySet()方法的返回这样的空对象.那么,这是我的问题,这些方法何时以及如何返回具有我们需要的元素的对象?
mas*_*tov 20
这是一种误解,认为Values班级"当然是空的".只是因为没有调用它的方法并且它的构造函数没有任何参数并不意味着该集合是空的.
所述Values类是一个"内部类"(非静态嵌套类的)HashMap,这意味着它具有的一个隐式引用HashMap创建它的对象.因此,它可以HashMap通过使用HashMap.this引用或直接访问成员来显式访问它的所有元素.由于它是一个内部类,甚至允许访问其HashMap私有成员.
您可以在Values类的实现size方法中看到:
public int size() {
return size;
}
Run Code Online (Sandbox Code Playgroud)
该Values班没有一个size成员,所以size指HashMap的规模.它相当于:
public int size() {
return HashMap.this.size;
}
Run Code Online (Sandbox Code Playgroud)
编辑:请注意,这也意味着您收到的集合不是副本,但仍然引用原始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]"
Run Code Online (Sandbox Code Playgroud)
Era*_*ran 13
本Values类实现了Collection由备份HashMap.正如mastov所评论的那样,Values是一个内部类HashMap,它允许它访问HashMap与之关联的封闭实例的成员.因此它不是空的.它的大小是它的大小HashMap,当你迭代它时,你正在迭代它的条目HashMap.
当你调用时System.out.println(values);,你正在调用toString方法AbstractCollection,它使用一个Iterator迭代值并获得它们的String表示.该Iterator过的条目的实际迭代HashMap,并返回其值.
对于Set由keySet和返回的s 也是如此entrySet.