为什么创建 HashMap 比创建 Object[] 更快?
Why is creating a HashMap faster than creating an Object[]?
我尝试构建自己的地图来提高特殊环境的性能,我发现了一些非常有趣的事情:创建 new Hashmap<Integer,String>(2000)
比 new Object[2000]
快 - 无论在哪个环境中命令我执行这些命令。这让我很困惑,尤其是。因为根据this,Hashmap构造函数包含一个table = new Entry[capacity]
。我的测试台有问题吗?
public static void test(int amm){ //amm=1_000_000
Map<Integer,String> m1 = null;
Object[] arr = null;
long time = System.nanoTime();
for(int i = 0; i < amm; i++){
m1 = new HashMap<Integer, String>(2000);
}
System.out.println("m1: " + (System.nanoTime() - time)); //m1: 70_455_065
time = System.nanoTime();
for(int i = 0; i < amm; i++){
arr = new Object[2000];
}
System.out.println("arr: " + (System.nanoTime() - time)); //arr: 1_322_473_803
}
我很想看看在另一台计算机上的测试结果。我不知道为什么创建 HashMap
比创建 Object[]
.
快 10 倍
一个空的 HashMap
对象比包含 2000 个 Object
引用的数组小得多。即使您将 2000 传递给 HashMap
构造函数的 initialCapacity
参数,它实际上还没有为对象创建 2000 个空间。
如果您查看 HashMap
的实现,构造函数如下所示:
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
threshold = initialCapacity;
init();
}
而 init()
看起来像:
/**
* Initialization hook for subclasses. This method is called
* in all constructors and pseudo-constructors (clone, readObject)
* after HashMap has been initialized but before any entries have
* been inserted. (In the absence of this method, readObject would
* require explicit knowledge of subclasses.)
*/
void init() {
}
所以initialCapacity
实际上并没有习惯于创建数组。它在哪里使用?查看 put()
方法。
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
// hidden
}
进行put操作时,实际上是创建了数组。我没有显示 inflateTable()
但它做了一些数学运算并初始化了数组。
我尝试构建自己的地图来提高特殊环境的性能,我发现了一些非常有趣的事情:创建 new Hashmap<Integer,String>(2000)
比 new Object[2000]
快 - 无论在哪个环境中命令我执行这些命令。这让我很困惑,尤其是。因为根据this,Hashmap构造函数包含一个table = new Entry[capacity]
。我的测试台有问题吗?
public static void test(int amm){ //amm=1_000_000
Map<Integer,String> m1 = null;
Object[] arr = null;
long time = System.nanoTime();
for(int i = 0; i < amm; i++){
m1 = new HashMap<Integer, String>(2000);
}
System.out.println("m1: " + (System.nanoTime() - time)); //m1: 70_455_065
time = System.nanoTime();
for(int i = 0; i < amm; i++){
arr = new Object[2000];
}
System.out.println("arr: " + (System.nanoTime() - time)); //arr: 1_322_473_803
}
我很想看看在另一台计算机上的测试结果。我不知道为什么创建 HashMap
比创建 Object[]
.
一个空的 HashMap
对象比包含 2000 个 Object
引用的数组小得多。即使您将 2000 传递给 HashMap
构造函数的 initialCapacity
参数,它实际上还没有为对象创建 2000 个空间。
如果您查看 HashMap
的实现,构造函数如下所示:
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
threshold = initialCapacity;
init();
}
而 init()
看起来像:
/**
* Initialization hook for subclasses. This method is called
* in all constructors and pseudo-constructors (clone, readObject)
* after HashMap has been initialized but before any entries have
* been inserted. (In the absence of this method, readObject would
* require explicit knowledge of subclasses.)
*/
void init() {
}
所以initialCapacity
实际上并没有习惯于创建数组。它在哪里使用?查看 put()
方法。
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
// hidden
}
进行put操作时,实际上是创建了数组。我没有显示 inflateTable()
但它做了一些数学运算并初始化了数组。