为什么创建HashMap比创建Object []更快?

ale*_*rne 44 java arrays performance hashmap

我已经尝试构建自己的Map以提高特殊环境的性能,并且我意识到一些非常有趣的事情:创建一个new Hashmap<Integer,String>(2000)比它更快new Object[2000]- 无论我执行这些命令的顺序如何.这对我来说非常困惑,尤其是 因为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
}
Run Code Online (Sandbox Code Playgroud)

我很想看到另一台计算机上的测试结果.我不知道为什么创建一个HashMap比创建一个快10倍Object[].

Ami*_*far 51

如果你看一下实现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();
}
Run Code Online (Sandbox Code Playgroud)

而且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() {
}
Run Code Online (Sandbox Code Playgroud)

所以initialCapacity实际上并没有习惯于创建一个数组.它在哪里使用?看看这个put()方法.

public V put(K key, V value) {
    if (table == EMPTY_TABLE) {
        inflateTable(threshold);
    }
    // hidden
} 
Run Code Online (Sandbox Code Playgroud)

在执行put时,实际创建了数组.我没有显示,inflateTable()但它做了一些数学并初始化数组.


Gre*_*ill 21

HashMap对象比2000个Object引用的数组小得多.即使你将2000传递给构造函数的initialCapacity参数HashMap,它实际上并没有为对象创建2000个空格.