繁体   English   中英

java.util.Map values()方法的性能

[英]java.util.Map values() method performance

我有一张这样的地图,其中包含几百万个条目:

private final Map<String, SomeItem> tops = new HashMap<>();

我需要获取值列表,这可以通过调用java.util.Map values()方法来完成。

问题

每次我调用此方法时都会创建值集合,或者它是预先计算的,从性能角度来看,它可以保存多次以进行调用?

问题是在我的情况下Map有数百万个元素,并且我不想每次调用values()都创建新列表

以下是java.util.HashMapMap.values()的复制实现:

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

这清楚地表明,除非有必要,否则不会创建值集合。 因此,不应因调用values()而造成额外的开销

这里重要的一点可能是: 没关系!


但是首先,请参考到目前为止的其他答案:在这里返回的集合通常是“缓存的”,因为它是惰性创建的,然后,将返回相同的实例。 例如,考虑HashMap类中的实现:

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

甚至AbstractMap文档 (大多数Map实现基于该文档 )中指定了(作为合同的一部分,作为实现规范):

该集合是在第一次调用此方法时创建的,并响应于所有后续调用而返回。 没有执行同步,因此有几次机会对该方法的多次调用不会全部返回相同的集合。


但是现在,有人可能会说实施可能会在以后更改。 HashMap类的实现可以更改,或者可以切换到另一种不扩展AbstractMap且以不同方式实现的Map实现。 当前这样实现的事实本身(本身)并不能保证它总是这样实现。

因此,更重要的一点(以及无关紧要的原因)是, values()方法确实应该返回一个集合视图 Map接口文档中所述

Map界面提供了三个集合视图 ,这些视图允许将地图的内容作为一组键,一组值或一组键-值映射来查看。

特别Map#values()方法文档

返回此映射中包含的值的Collection视图。 集合由地图支持,因此对地图的更改会反映在集合中,反之亦然。

我无法想象实现包含处理Map所有值的视图的合理方法。


例如,假设HashMap中的实现是这样的:

public Collection<V> values() {
    return new Values();
}

然后,它将在每次调用时返回一个新的集合。 但是创建此集合根本涉及处理值。

或这样说:调用此方法的成本与地图的大小无关 无论地图包含10个元素还是10000个元素,它基本上都需要创建单个对象。

正如其他人提到的那样,您可以通过查看代码来看到这一点。 您还可以编写一个快速示例来向自己证明。 下面的代码将打印正确的10次,因为对象标识的值始终相同。

public static void main(String[] args) {
    Map<String, String> myMap = new HashMap();
    Collection<String> lastValues = myMap.values();
    for (int i=0; i < 10; i++) {
        System.out.println(lastValues == myMap.values());
        lastValues = myMap.values();
    }
}

下面的代码将在第一次打印true,然后在接下来的9次false。

public static void main(String[] args) {
    Map<String, String> myMap = new HashMap();
    Collection<String> lastValues = myMap.values();
    for (int i=0; i < 10; i++) {
        System.out.println(lastValues == myMap.values());
        lastValues = myMap.values();
        myMap = new HashMap();
    }
}

阅读此主题后,还有一个建议,如果Map顶部声明的内容未更改-您可以使用google guava ImmutableMap对象。 有关更多信息-UnmodifiableMap(Java Collections)与ImmutableMap(Google)

暂无
暂无

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

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