【发布时间】:2014-09-05 05:27:17
【问题描述】:
我正在经历 Java 8 HashMap 的改进,显示使用二叉树的搜索性能提高了大约 20%。
当时有一个想法是如何影响插入性能。所以我开始插入几百万条记录。下面是代码 sn-p 和不同的结果集。
import java.util.HashMap;
import java.util.Map;
public class MapWriter {
public static final int MAX_KEY = 1_000_000;
private Map<Double, Double> map = new HashMap<>(MAX_KEY);
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
MapWriter writer = new MapWriter();
for (int i = 0; i < MAX_KEY; i++) {
double random = Math.random();
writer.map.put(random, random);
}
long timeTaken = System.currentTimeMillis() - startTime;
System.out.println("Total Time Taken = " + timeTaken);
System.out.println("Map Size = " + writer.map.size());
}
}
以下是不同的结果:
-
1000 万次插入
-
Java 7
- 总耗时 = 23145
-
Java 8
- 总耗时 = 64964
-
-
200 万次插入
- Java 7
- 总耗时 = 6628
- Java 8
- 总耗时 = 8312
- Java 7
-
100 万次插入
- Java 7
- 总耗时 = 3577
- Java 8
- 总耗时 = 1212
- Java 7
结果表明,Java 8 的插入次数最多可达 100 万次。但是当你向上移动时,结果显示出相反的行为。
我该如何解释这种行为??????
更新:感谢大家的宝贵反馈。我需要了解有关基准测试的更多信息。我预先初始化了 Math.random 部分,结果对于 java 7 和 java 8 都是一样的。这是修改后的代码。如果从基准测试的角度来看代码看起来仍然很臭,请告诉我。
public class MapWriter {
public static int MAX_KEY = 1_000_000;
private Map<Double, Double> map = new HashMap<>(MAX_KEY);
public static void main(String[] args) {
MAX_KEY = Integer.parseInt(args[0]);
Double[] keys = new Double[MAX_KEY];
for(int i = 0; i < MAX_KEY; i++) {
keys[i] = Math.random();
}
MapWriter writer = new MapWriter();
for (int i = 0; i < 100000; i++) {
writer.map.put(keys[i], keys[i]);
}
writer.map = new HashMap<>(MAX_KEY);
long startTime = System.nanoTime();
for (int i = 0; i < MAX_KEY; i++) {
double random = Math.random();
writer.map.put(random, random);
}
long timeTaken = System.nanoTime() - startTime;
System.out.println("Total Time Taken = " + timeTaken / 1000000);
System.out.println("Map Size = " + writer.map.size());
}
}
【问题讨论】:
-
我认为这种基准测试方法过于幼稚。您可能没有考虑的因素太多了。
-
是否有证据表明 Java 8 的
HashMap使用了二叉树?听起来不对。 -
@EJP 是的,请参阅HashMap.java,尤其是从第 143 行开始的实现说明。简而言之,如果哈希冲突导致任何 bin 中的人口过多,则该 bin 将从链表转换为二叉树。