[英]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.