ArrayList每次显示不同的执行时间为什么?

时间:2013-08-11 07:01:54

标签: java performance collections arraylist indexing

我正在使用ArrayList并尝试在预先填充new object ArrayListArrayList的{​​{1}}开头添加3000000

根据我的知识,它会在第一个索引处添加新对象,并将下面的所有记录移动到之前的位置。每当我将新对象添加到该数组列表时,就会发生这种情况。意味着执行时间应该相同(可能会发生很小的变化)。

但是当我添加新的记录时,它显示0和一些时间15。

这是我的程序

package com.rais;

import java.util.ArrayList;
import java.util.List;

public class ArrayListTest {

    public static List<String> arrList = new ArrayList<String>();
    static {
        for (int i = 0; i < 3000000; i++) {
            arrList.add("Hello"+i);
        }
    }


    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {

            long startTime = System.currentTimeMillis();

            arrList.add(0,"Rais"+i);

            long endTime = System.currentTimeMillis();
            System.out.println("Total execution time ="+(endTime-startTime));


        }
       }

    }

这是该程序的输出。

Total execution time =0
Total execution time =0
Total execution time =15
Total execution time =0
Total execution time =0

我很困惑,为什么它显示0。它应该每次显示15或者接近15,但它不应该显示为0.

4 个答案:

答案 0 :(得分:4)

问题可能是您从currentTimeMillis()的文档中测量的方式;

  

以毫秒为单位返回当前时间。请注意,虽然返回值的时间单位是毫秒,但值的粒度取决于基础操作系统,可能更大。例如,许多操作系统以几十毫秒为单位测量时间。

换句话说,如果currentTimeMillis在您的系统上具有接近15ms的粒度,那么即使操作总是花费相同的时间,您也将获得0或15ms,稍微随机,具体取决于开始时间。

答案 1 :(得分:1)

我无法解释您看到的结果,但我怀疑它们至少部分是由您编写的简单基准代码引起的。

高质量的基准测试代码可运行数百或数千次迭代,并且由于重新编译和运行时优化而对性能变化很敏感。一般来说,System.nanoTime()也用于这些计算。

请参阅this excellent article from IBM,了解如何以强大的方式进行基准测试。本文最后提出了一个框架,可用于根据最佳实践执行基准测试。

答案 2 :(得分:1)

正如其他答案所述,这可能是时钟粒度的问题。您可以使用以下代码检查是否是这种情况:

public static void main(String[] args) {
    try {
        for (int i = 0; i < 30; i++) {

            long startTimeMillis = System.currentTimeMillis();
            long startTimeNanos = System.nanoTime();

            Thread.sleep(11);

            long endTimeMillis = System.currentTimeMillis();
            long endTimeNanos = System.nanoTime();
            System.out.println("Total execution time ="
                + (endTimeMillis-startTimeMillis)+" ms / "
                + (endTimeNanos-startTimeNanos)+" ns");
        }

    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

另一种(不太可能)的可能性是ArrayList中的数组已达到容量,并且正在扩展(由更大的数组替换)。

答案 3 :(得分:0)

最有可能的原因是你没有得到准确的时间是因为currentTimeMillis()不够精确,不能测量它。做一个10000的循环,然后看看你得到了什么。添加到ArrayList可能需要几微秒,而不是毫秒(通常情况下)。你看到的15ms可能是由于垃圾收集或其他原因造成的延迟 - 但无论如何,你的采样太小而无法获得准确的结果。