从一些资源中,我了解到在Java集合下,ArrayList
比 Vector
快。为了检查这一点,我尝试使用一个小程序,其中一种方法将一些数据添加到 ArrayList
中。然后检索这些数据,另一种方法将相同的数据添加到 Vector
或从中检索相同的数据。现在main()
方法在两个不同的时间计算过程下调用其中两个方法,分别计算这些方法的执行时间。结果,我得到 ArrayList
的执行时间是 18385831 ns,Vector
是 2190242 纳秒。我的项目负责人还说 ArrayList
比 Vector
快。但我的程序的结果却说了一些不同的东西。谁能向我解释正确的事情及其原因吗?也是这个结果的原因如果 ArrayList
确实比 Vector
快.
这是我的源代码:
import java.util.*;
public class TestArraylist {
void Arraylistpart() {
ArrayList<Object> a1 = new ArrayList<Object>();
ArrayList<Object> a2 = new ArrayList<Object>();
a2 = a1;
a1.add(1);
a1.add('c');
a1.add("gh");
a1.add(2);
a1.set(2, "ab");
int count = 0;
System.out.println(a1);
try {
for (Object i : a1) {
a2.set(count, i.toString());
count = count + 1;
}
a2.sort(null);
System.out.println(a2);
} catch (ClassCastException e) {
System.err.println("Exception occurs");
}
}
void vectorpart() {
Vector<Object> v1 = new Vector<Object>();
Vector<Object> v2 = new Vector<Object>();
v2 = v1;
v1.add(1);
v1.add('c');
v1.add("ab");
v1.add(2);
int count1 = 0;
System.out.println(v1);
try {
for (Object i : v1) {
v2.setElementAt(i.toString(), count1);
count1 = count1 + 1;
}
v2.sort(null);
System.out.println(v2);
} catch (ClassCastException e) {
System.err.println("Exception occurs");
}
}
public static void main(String[] args) {
TestArraylist objct = new TestArraylist();
System.out.println("Arraylist program");
long startmili = System.currentTimeMillis();
long starttime = System.nanoTime();
objct.Arraylistpart();
long endtime = System.nanoTime();
long endmili = System.currentTimeMillis();
long totaltime = endtime - starttime;
long totaltimemili = endmili - startmili;
System.out.println(totaltime);
System.out.println("Time in mili is: " + totaltimemili);
System.out.println("\nVector program");
long startmili1 = System.currentTimeMillis();
long starttime1 = System.nanoTime();
objct.vectorpart();
long endtime1 = System.nanoTime();
long endmili1 = System.currentTimeMillis();
long totaltime1 = endtime1 - starttime1;
long totaltimemili1 = endmili1 - startmili1;
System.out.println(totaltime1);
System.out.println("Time in mili is: " + totaltimemili1);
}
}
最佳答案
你的基准是错误的。首先,您不仅测量了基于数组/vector 的操作的时间,还测量了打印时间,这可能比其他所有操作都要慢几个数量级。其次,您没有进行预热,因此您的大部分代码可能是由解释器执行的,而不是 JIT 编译的。第三,在同一个 JVM 中启动两个测试,将它们置于不平等的条件下:在第一个测试执行期间,JVM 执行更多的预热步骤(例如 JIT 编译),因此第一个测试从一开始就受到阻碍。让我们尝试使用 JMH 编写一些等效的内容。 :
import org.openjdk.jmh.annotations.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Warmup(iterations = 20, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 20, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Fork(1)
@State(Scope.Benchmark)
public class TestArraylist {
@Benchmark
public String Arraylistpart() {
ArrayList<Object> a1 = new ArrayList<>();
ArrayList<Object> a2 = new ArrayList<>();
a2 = a1;
a1.add(1);
a1.add('c');
a1.add("gh");
a1.add(2);
a1.set(2, "ab");
int count = 0;
for (Object i : a1) {
a2.set(count, i.toString());
count = count + 1;
}
a2.sort(null);
return a1.toString()+a2.toString();
}
@Benchmark
public String vectorpart() {
Vector<Object> v1 = new Vector<>();
Vector<Object> v2 = new Vector<>();
v2 = v1;
v1.add(1);
v1.add('c');
v1.add("ab");
v1.add(2);
int count1 = 0;
for (Object i : v1) {
v2.setElementAt(i.toString(), count1);
count1 = count1 + 1;
}
v2.sort(null);
return v1.toString()+v2.toString();
}
}
我返回了 a1.toString()+a2.toString()
而不是打印以保留 .toString()
调用(这是在您的测试中完成的 System.out.println
)。
总结结果如下:
Benchmark Mode Cnt Score Error Units
TestArraylist.Arraylistpart avgt 20 0,382 ± 0,003 us/op
TestArraylist.vectorpart avgt 20 0,421 ± 0,002 us/op
看,您的测试实际上执行得快得多。只有382纳秒和421纳秒。由于额外的同步,Vector 确实有点慢。但似乎C2 JIT编译器很好地删除了一些不必要的同步部分,因此时间差异不是很大。检查每次迭代的统计数据也很有趣。对于ArrayList:
# Warmup Iteration 1: 0,544 us/op
# Warmup Iteration 2: 0,471 us/op
# Warmup Iteration 3: 0,383 us/op
# Warmup Iteration 4: 0,377 us/op
# Warmup Iteration 5: 0,377 us/op
# Warmup Iteration 6: 0,373 us/op
...
Iteration 14: 0,374 us/op
Iteration 15: 0,376 us/op
Iteration 16: 0,381 us/op
Iteration 17: 0,376 us/op
Iteration 18: 0,379 us/op
Iteration 19: 0,383 us/op
Iteration 20: 0,385 us/op
对于 vector
:
# Warmup Iteration 1: 0,889 us/op
# Warmup Iteration 2: 0,630 us/op
# Warmup Iteration 3: 0,689 us/op
# Warmup Iteration 4: 0,662 us/op
# Warmup Iteration 5: 0,671 us/op
# Warmup Iteration 6: 0,673 us/op
# Warmup Iteration 7: 0,669 us/op
# Warmup Iteration 8: 0,657 us/op
# Warmup Iteration 9: 0,427 us/op
# Warmup Iteration 10: 0,421 us/op
# Warmup Iteration 11: 0,421 us/op
...
Iteration 17: 0,423 us/op
Iteration 18: 0,420 us/op
Iteration 19: 0,422 us/op
Iteration 20: 0,419 us/op
如您所见,ArrayList
在第 3 次迭代中达到全速,而 Vector
在第 9 次迭代中达到全速。
关于Java Collection-ArrayList 和 Vector 之间的加速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35788759/