简体   繁体   English

HashMap.values()和HashMap.keySet()如何返回值和键?

[英]How do HashMap.values() and HashMap.keySet() return values and keys?

The source code of HashMap.values() is shown as follows HashMap.values()的源代码如下所示

public Collection<V> values() {
    Collection<V> vs = values;
    return (vs != null ? vs : (values = new Values()));
}

As you can see, when the values() method first called, it just returns a Values object. 如您所见,当values()方法首次调用时,它只返回一个Values对象。 The Values object is a subclass of AbstractCollection with no constructor, and of course contains no element. Values对象是AbstractCollection的子类,没有构造函数,当然不包含任何元素。 But when I called the method, it returned a collection rapidly 但是当我调用该方法时,它会快速返回一个集合

Collection<String> values = map.values();
System.out.println(values);

That's so weird. 那太奇怪了。 Not only values() , but also keySet() and entrySet() method return such empty objects. 不仅values() ,而且keySet()entrySet()方法返回这样的空对象。 So, here is my question, when and how do these methods return objects with elements we need? 那么,这是我的问题,这些方法何时以及如何返回具有我们需要的元素的对象?

It's a misconception that the Values class is "of course empty". 错误的观点是, Values类“当然是空的”。 Just because there is no method called on it and its constructor doesn't have any arguments doesn't mean that the collection is empty. 只是因为没有调用它的方法并且它的构造函数没有任何参数并不意味着该集合是空的。

The Values class is an "inner class" (a non-static nested class ) of HashMap , which means that it has an implicit reference to the HashMap object that created it. Values类是HashMap的“内部类”(非静态嵌套类 ),这意味着它具有对创建它的HashMap对象的隐式引用。 It can therefore access all elements of the HashMap , either explicitly by using the HashMap.this reference or by just accessing the members directly. 因此,它可以通过使用HashMap.this引用或直接访问成员来显式访问HashMap所有元素。 Since it is an inner class, it is even allowed to access the HashMap 's private members. 由于它是一个内部类,甚至允许访问HashMap的私有成员。

You can see that for example in the Values class' implementation of the size method: 您可以在Values类的size方法实现中看到:

public int size() {
    return size;
}

The Values class doesn't have a size member, so that size refers to the HashMap 's size. Values类没有size成员,因此size指的是HashMap的大小。 It's equivalent to: 它相当于:

public int size() {
    return HashMap.this.size;
}

EDIT: Note that this also means that the collection you receive is not a copy, but still refers to the original HashMap contents and therefore changes when you update the HashMap : 编辑:请注意,这也意味着您收到的集合不是副本,但仍然引用原始的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]"

The Values class implements a Collection that is backed by the HashMap . Values类实现了由HashMap支持的Collection As mastov commented, Values is an inner class of HashMap , which gives it access to the members of the enclosing HashMap instance it is associated with. 正如mastov所评论的, ValuesHashMap的内部类,它允许访问与之关联的封闭HashMap实例的成员。 Therefore it's not empty. 因此它不是空的。 Its size is the size of the HashMap , and when you iterate over it, you are iterating over the Entries of the HashMap . 它的大小是HashMap的大小,当你迭代它时,你正在迭代HashMap的条目。

When you call System.out.println(values); 当你调用System.out.println(values); , you are calling the toString method of AbstractCollection , which uses an Iterator to iterate over the values and get their String representation. ,您正在调用AbstractCollectiontoString方法,该方法使用Iterator迭代值并获取其String表示形式。 The Iterator actually iterates over the Entries of the HashMap and returns their values. Iterator实际上遍历HashMap的条目并返回它们的值。

The same goes for the Set s returned by keySet and entrySet . 对于keySetentrySet返回的Set ,情况也是如此。

Collection<V> vs = values;
return (vs != null ? vs : (values = new Values()));

These two line answer your question. 这两行回答了你的问题。

values is a internal collection (Inherited from AbstractMap ). values是一个内部集合(从AbstractMap继承)。 If it is not null then it will be returned. 如果它不为null则返回它。
If it is null then it will be initialized and the new one will returned. 如果它为null则它将被初始化并返回新的。

Now I guess, the main point of your question is 现在我想,你的问题的主要观点是
when and how do these methods return objects with elements we need? 何时以及如何使用我们需要的元素返回对象?

Technically values always return this initialized Object. 技术上, values始终返回此初始化对象。 Then how we get our entry values from these object.? 那么我们如何从这些对象中获取入口值。
Lets go a little deep: 让我们走得更远:

values() actually return an object of class Values which is an Inner class of HashMap and extends AbstractCollection values()实际上返回类Values的对象,它是HashMap的Inner类,并扩展了AbstractCollection

private final class Values extends AbstractCollection<V> 

As you have looked into the source code. 正如您已查看源代码。 Then you will find inside the Values class 然后你会在Values类中找到它

public Iterator<V> iterator() {
        return newValueIterator();
    }

this newValueIterator() does the trick. 这个newValueIterator()可以解决问题。
If you go more deeper you will find newValueIterator() returns object of ValueIterator which is a subclass of HashIterator HashIterator implements basic functionality for iteration, which actually itterate over the table maintained by the HashMap . 如果你更深入,你会发现newValueIterator()返回ValueIterator对象,它是HashIterator的子类HashIterator实现迭代的基本功能,它实际上是在HashMap维护的table

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM