Javaでサイズnの配列を宣言する実行時間はどれくらいですか?これは、ガベージコレクションでメモリがゼロになるか(この場合はO(1))である可能性があります)、または初期化であるか(この場合は必要です)に依存すると思います。 be O(n))。
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に依存すると思います。これが当てはまるかどうかを確認するために、大まかなベンチマークを行うことができます。
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)と仮定します。もちろん、それだけでは十分ではありませんが、それはヒントです。
配列が割り当てられるとメモリが初期化されるので、O(n)であると確信しています。 O(n)より高くするべきではなく、O(n)より小さくする方法がわからないので、それが唯一の選択肢のようです。
さらに詳しく説明すると、Javaは割り当て時に配列を初期化します。メモリ領域を移動せずにゼロにする方法はなく、領域のサイズによって命令の数が決まります。したがって、メモリの領域は低くなります。境界はO(n)です。また、線形解があるため、線形よりも遅いゼロ化アルゴリズムを使用しても意味がありません。したがって、上限はO(n)である必要があります。したがって、O(n)が意味のある唯一の答えです。
ただし、楽しみのために、OSがメモリの個々の領域への電力を制御し、電源をオフにしてからオンにすることで領域をゼロにすることができる奇妙なハードウェアを想像してみてください。これはO(1)のようです。ただし、領域はユーティリティが消える前にのみ大きくなる可能性があるため(すべてを失いたくない)、領域をゼロにするように要求すると、除数が大きい場合でもO(n)になります。
テストしてみましょう。
_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)での結果:
したがって、明らかにO(n)
のように見えますが、約500万要素でより効率的なメソッドに切り替わっているようにも見えます。