我有一张这样的地图,有数百万条:
private final Map<String, SomeItem> tops = new HashMap<>();
我需要获取值列表,可以通过调用java.util.Map values()
方法来完成。
问题:
每次调用此方法时都会创建值集合,或者它是预先计算出来的,并且从性能角度保存它以多次调用它?
问题在于,在我的情况下,Map
有数百万个元素,每次调用values()
时我都不想创建新列表
答案 0 :(得分:3)
以下是<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>demo</groupId>
<artifactId>demo_batch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo_batch</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
中$my_var = file_get_contents('http://example.com/token.php');
echo $my_var;
的复制实施:
Map.values()
这清楚地表明除非必要,否则不会创建值集合。因此,调用java.util.HashMap
答案 1 :(得分:1)
这里的一个重点可能是:没关系!
但首先,参考到目前为止的其他答案:在那里返回的集合通常是“缓存”,因为它是懒惰创建的,之后,将返回相同的实例。例如,考虑HashMap
类中的实现:
public Collection<V> values() {
Collection<V> vs;
return (vs = values) == null ? (values = new Values()) : vs;
}
documentation of the AbstractMap
class(大多数Map
实现所依据的)甚至指定了(作为合同的一部分,作为实现规范):
首次调用此方法时会创建该集合,并在响应所有后续调用时返回该集合。没有执行同步,因此对此方法的多次调用很可能不会返回同一个集合。
但是现在,人们可能会争辩说实施可能会在以后发生变化。 HashMap
类的实现可能会发生变化,或者可能会切换到不扩展Map
的另一个AbstractMap
实现,并且实现方式也不同。它是当前这样实现的事实(对于它自己)并不能保证总是像这样实现。
因此,更重要的一点(以及无关紧要的原因)是values()
方法确实应该返回集合视图。如documentation of the Map
interface中所述:
Map接口提供了三个集合视图,它们允许将地图的内容视为一组键,值集合或键值映射集。
具体而言,documentation of the Map#values()
method:
返回此地图中包含的值的Collection视图。该集合由地图支持,因此对地图的更改将反映在集合中,反之亦然。
我无法想象实现涉及处理Map
的所有值的视图的合理方法。
例如,假设HashMap
中的实现是这样的:
public Collection<V> values() {
return new Values();
}
然后每次调用它时都会返回 new 集合。但是创建此集合确实不涉及处理值。
或者这样说:调用此方法的成本是独立的大小。它基本上具有单个对象创建的成本,无论地图是否包含10或10000个元素。
答案 2 :(得分:0)
正如其他人所提到的,你可以通过查看代码来看到这一点。您还可以编写一个快速示例来向自己证明。下面的代码将打印为真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();
}
}
答案 3 :(得分:0)
阅读此主题后的另一个建议是,如果Map tops声明的内容未更改 - 您可以使用google guava ImmutableMap对象。有关详细信息,请访问UnmodifiableMap (Java Collections) vs ImmutableMap (Google)