Java:声明一个大小为n的数组的大时间是什么?

时间:2011-04-12 19:56:05

标签: java arrays complexity-theory performance

在Java中声明大小为n的数组的运行时间是多少?我想这将取决于内存是否在垃圾收集(在这种情况下可能是O(1))或初始化(在这种情况下它必须是O(n))归零。

4 个答案:

答案 0 :(得分:18)

这是O(n)。考虑一下这个简单的程序:

public class ArrayTest {

  public static void main(String[] args) {
     int[] var = new int[5];
  }

}

生成的字节码是:

Compiled from "ArrayTest.java"
public class ArrayTest extends java.lang.Object{
public ArrayTest();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   iconst_5
   1:   newarray int
   3:   astore_1
   4:   return

}

要查看的指令是newarray指令(只搜索newarray)。来自VM规范:

  

从垃圾收集堆中分配一个新数组,其组件类型为atype且长度为count。此新数组对象的引用arrayref被推入操作数堆栈。 新数组的每个元素都初始化为数组类型的默认初始值(§2.5.1)。

由于每个元素都在初始化,因此需要O(n)时间。

修改

查看提供的链接amit,可以在常量时间内使用默认值实现数组初始化。所以我猜它最终取决于JVM。你可以做一些粗略的基准测试,看看是否是这种情况。

答案 1 :(得分:8)

关于JRE1.6的小型无专业基准:

public static void main(String[] args) {
    long start = System.nanoTime();
    int[] x = new int[50];
    long smallArray = System.nanoTime();
    int[] m = new int[1000000];
    long bigArray = System.nanoTime();
    System.out.println("big:" +  new Long( bigArray - smallArray));
    System.out.println("small:" +  new Long( smallArray - start));


}

给出了以下结果:

big:6133612
small:6159

所以我假设O(n)。 当然,这还不够确定,但这是一个提示。

答案 2 :(得分:4)

我很确定它是O(n),因为在分配数组时内存已初始化。它不应该高于O(n),并且我认为没有办法使它小于O(n),所以这似乎是唯一的选择。

进一步详细说明,Java在分配时初始化数组。如果没有走过它就无法将内存区域归零,并且区域的大小决定了指令的数量。因此,下限是O(n)。此外,使用比线性更慢的归零算法是没有意义的,因为存在线性解,因此上限必须是O(n)。因此,O(n)是唯一有意义的答案。

但是,只是为了好玩,想象一个奇怪的硬件,操作系统可以控制单个内存区域的电源,并可以通过关闭电源然后再打开来使区域归零。这似乎是O(1)。但是一个区域只能在实用程序消失之前变得如此之大(不想丢失所有东西),所以要求将一个区域归零仍然是O(n)有一个大的除数。

答案 3 :(得分:2)

我们来试试吧。

class ArrayAlloc {
  static long alloc(int n) {
    long start = System.nanoTime();
    long[] var = new long[n];
    long total = System.nanoTime() - start;
    var[n/2] = 8;
    return total;
  }
  public static void main(String[] args) {
    for(int i=1; i<100000000; i+=1000000) {
      System.out.println(i + "," + alloc(i));
    }
  }
}

我的linux笔记本电脑上的结果(i7-4600M @ 2.90GHz):

Time taken by the initialization of a java array of size n

所以它显然看起来像O(n),但看起来它也转换为一个更有效的方法,大约有500万个元素。