简体   繁体   English

为什么创建初始容量较慢的ArrayList?

[英]Why is creating ArrayList with initial capacity slow?

Comparing creating large ArrayList with intialCapacity I found that it;s slower than creting it without one. 比较创建大型ArrayList和intialCapacity,我发现它;比没有一个更快地创建它。 Here is the simple program I wrote to measure it: 这是我编写的用于衡量它的简单程序:

long start2 = System.nanoTime();
List<Double> col = new ArrayList<>(30000000); // <--- Here
for (int i = 0; i < 30000000; i++) {
    col.add(Math.sqrt(i + 1));
}
long end2 = System.nanoTime();
System.out.println(end2 - start2);
System.out.println(col.get(12411325).hashCode() == System.nanoTime());

The average result for new ArrayList<>(30000000) : 6121173329 ArrayList<>(30000000)的平均结果: 6121173329

The average result for new ArrayList<>() : 4883894100 ArrayList<>()的平均结果: 4883894100

on my machine. 在我的机器上。 I thought that it would be faster to create large array once rather than reacreating it once we go beyond the capacity of the current underlying array of ArrayList . 我认为,一旦我们超出当前的ArrayList底层数据的容量,创建一次大型数组会更快,而不是重新创建它。 Eventually we should have ended up with array size greater or equal than 30000000 . 最终我们应该最终得到大于或等于30000000数组大小。

I thought it was optimization, but actualy pessimization. 我认为这是优化,但实际上是悲观。 Why that? 为什么?

I ran the same program multiple times. 我多次运行同一个程序。 It was not in a loop 它不在一个循环中

Consider how you are profiling the code - if you include both a 'ramp up time' (to take into account things such as JIT ) and average over several calls (to gather some statistics/distribution), the timing may lead you to a different conclusion. 考虑一下如何分析代码 - 如果你同时包括'加速时间' (考虑JIT之类的事情)和平均多次调用(收集一些统计数据/分布),时间可能会导致你变得不同结论。 For example: 例如:

public static void main(String[] args){
    //Warm up
    System.out.println("Warm up");
    for ( int i = 0; i < 5; i++ ){
        dynamic();
        constant();
    }
    System.out.println("Timing...");
    //time
    long e = 0;
    long s = 0; 
    int total = 5;
    for ( int i = 0; i < total; i++ ){
        long e1 = dynamic();
        System.out.print(e1 + "\t");
        e += e1;
        long s1 = constant();
        System.out.println(s1);
        s += s1;
    }
    System.out.println("Static Avg: " + (s/total));
    System.out.println("Dynamic Avg: " + (e/total));

}

private static long dynamic(){
    long start2 = System.currentTimeMillis();
    List<Double> col = new ArrayList<>();
    for (int i = 0; i < 30000000; i++) {
        col.add(Math.sqrt(i + 1));
    }
    long end2 = System.currentTimeMillis();
    return end2 - start2;
}

private static long constant(){
    long start2 = System.currentTimeMillis();
    List<Double> col = new ArrayList<>(30000000); 
    for (int i = 0; i < 30000000; i++) {
        col.add(Math.sqrt(i + 1));
    }
    long end2 = System.currentTimeMillis();
    return end2 - start2;
}

On my system setting the initial capacity is always faster, though not by any orders of magnitude. 在我的系统设置中,初始容量总是更快,但不是任何数量级。

Edit: As suggested in a comment, consider reading through How do I write a correct micro-benchmark in Java? 编辑:正如评论中所建议的,请仔细阅读如何在Java中编写正确的微基准测试?

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

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