列挙が Iterator よりも速いのはなぜですか? ただし、イテレータには列挙よりも多くの利点があります。
質問する
3366 次
1 に答える
1
Enumeration は、古いスレッド セーフ コレクションでのみ使用できることに注意してください。Iterator の使用は任意のコレクションで使用でき、スレッドセーフである必要がないため、追加のロック オーバーヘッドはありません。
public static void main(String... args) {
Vector<Integer> vec = new Vector<>();
ArrayList<Integer> al = new ArrayList<>();
polulate(vec);
polulate(al);
for (int i = 0; i < 5; i++) {
long start = System.nanoTime();
long sum1 = enumSumOf(vec);
long mid1 = System.nanoTime();
long sum1b = iterSumOf(vec);
long mid2 = System.nanoTime();
long sum2 = iterSumOf(al);
long end = System.nanoTime();
System.out.printf("Each iteration of Enumeration took %,d ns (Vector), Iteration took %,d ns (Vector), Iteration took %,d ns (ArrayList)%n",
(mid1 - start) / vec.size(), (mid2 - mid1) / vec.size(), (end - mid2) / al.size());
}
}
private static long enumSumOf(Vector<Integer> vec) {
long sum = 0;
for (Enumeration<Integer> e = vec.elements(); e.hasMoreElements(); )
sum += e.nextElement();
return sum;
}
private static long iterSumOf(Vector<Integer> al) {
long sum = 0;
for (int i : al)
sum += i;
return sum;
}
private static long iterSumOf(ArrayList<Integer> al) {
long sum = 0;
for (int i : al)
sum += i;
return sum;
}
private static void polulate(List<Integer> l) {
for (int i = 0; i < 1000000; i++)
l.add(i);
}
版画
Each iteration of Enumeration took 61 ns (Vector),
Iteration took 74 ns (Vector), Iteration took 17 ns (ArrayList)
Each iteration of Enumeration took 52 ns (Vector),
Iteration took 54 ns (Vector), Iteration took 6 ns (ArrayList)
Each iteration of Enumeration took 52 ns (Vector),
Iteration took 54 ns (Vector), Iteration took 6 ns (ArrayList)
Each iteration of Enumeration took 52 ns (Vector),
Iteration took 53 ns (Vector), Iteration took 6 ns (ArrayList)
Each iteration of Enumeration took 40 ns (Vector),
Iteration took 36 ns (Vector), Iteration took 5 ns (ArrayList)
与えられたマイクロベンチマークの例では、Enumeration が Iterator よりも速い理由は、最初にテストされるためです。;)
より長い答えは、ループが 10,000 回繰り返されると、HotSpot コンパイラがメソッド全体を最適化するというものです。これ-XX:CompileThreshold=NNNN
は、2 つのループがある場合と同じ方法で変更できます。
- 2 番目のループは開始前に最適化されているのに対し、実行された時間によっては最適化されていないため、最初のテストは遅くなります。
- 2 番目のテストは、JVM が実行時に最適化メトリックを収集し、それらのメトリックを使用してコードを最適化するため、時間がかかります。メトリクスが収集される前にコードが最適化されると、はるかに遅くなる可能性があります。
これを示す簡単な方法は、ループの順序を入れ替えることです。より良い解決策は、各ループを独自のメソッドに配置し、テストを数回繰り返すことです。これにより、それらが個別に最適化され、結果が再現可能になります。
于 2012-06-14T08:14:09.340 に答える