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

时间:2015-06-08 11:47:58

标签: java hashmap

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()方法返回此类空对象。所以,这是我的问题,这些方法何时以及如何返回具有我们需要的元素的对象?

3 个答案:

答案 0 :(得分:20)

这是一种误解,Values课程是&#34;当然是空的&#34;。只是因为没有调用它的方法,它的构造函数没有任何参数并不意味着该集合是空的。

Values班级是一个内部班级&#34; ({1}}的非静态nested class),这意味着它具有对创建它的HashMap对象的隐式引用。因此,它可以通过使用HashMap引用或直接访问成员来显式访问HashMap的所有元素。由于它是一个内部类,甚至可以访问HashMap.this的私人成员。

例如,您可以在HashMap课程中看到&#39; Values方法的实现:

size

public int size() { return size; } 班级没有Values成员,因此size指的是size的尺寸。它相当于:

HashMap

编辑:请注意,这也意味着您收到的收藏品不是副本,但仍会引用原始public int size() { return HashMap.this.size; } 内容,因此更新{{1}时会发生变化}:

HashMap

答案 1 :(得分:13)

Values类实现Collection支持的HashMap。正如mastov评论的那样,ValuesHashMap的内部类,它允许访问与之关联的封闭HashMap实例的成员。因此它不是空的。它的大小是HashMap的大小,当你迭代它时,你正在迭代HashMap的条目。

当您致电System.out.println(values);时,您正在调用toString AbstractCollection方法,该方法使用Iterator来迭代这些值并获取String表示。 Iterator实际上迭代HashMap的条目并返回它们的值。

SetkeySet返回的entrySet也是如此。

答案 2 :(得分:2)

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

这两行回答了你的问题。

values是一个内部集合(继承自AbstractMap)。如果不是null,则会返回 如果是null,那么它将被初始化并返回新的。

现在我猜,你问题的主要内容是
这些方法何时以及如何使用我们需要的元素返回对象?

技术上values始终返回此初始化对象。那么我们如何从这些对象中获取入口值。?
让我们走得更远:

values()实际返回类Values的对象,该对象是HashMap的内部类并扩展AbstractCollection

private final class Values extends AbstractCollection<V> 

您已查看过源代码。然后你会在Values

里面找到
public Iterator<V> iterator() {
        return newValueIterator();
    }

这个newValueIterator()可以解决问题 如果你更深入,你会发现newValueIterator()返回ValueIterator的对象,HashIteratorHashIterator的子类 table实现了迭代的基本功能,实际上迭代了HashMap维护的select SUBSTRING('SH1684|32I5', 1, CHARINDEX('|', 'SH1684|32I5') -1) AS ID