我一直认为我们应该在Java中使用Vector,并且没有性能问题,这当然是正确的。我正在编写一种计算MSE(均方误差)的方法,并注意到它非常慢 - 我基本上是传递了值的向量。当我切换到Array时,速度提高了10倍,但我不明白为什么。
我写了一个简单的测试:
public static void main(String[] args) throws IOException {
Vector <Integer> testV = new Vector<Integer>();
Integer[] testA = new Integer[1000000];
for(int i=0;i<1000000;i++){
testV.add(i);
testA[i]=i;
}
Long startTime = System.currentTimeMillis();
for(int i=0;i<500;i++){
double testVal = testArray(testA, 0, 1000000);
}
System.out.println(String.format("Array total time %s ",System.currentTimeMillis() - startTime));
startTime = System.currentTimeMillis();
for(int i=0;i<500;i++){
double testVal = testVector(testV, 0, 1000000);
}
System.out.println(String.format("Vector total time %s ",System.currentTimeMillis() - startTime));
}
调用以下方法:
public static double testVector(Vector<Integer> data, int start, int stop){
double toto = 0.0;
for(int i=start ; i<stop ; i++){
toto += data.get(i);
}
return toto / data.size();
}
public static double testArray(Integer[] data, int start, int stop){
double toto = 0.0;
for(int i=start ; i<stop ; i++){
toto += data[i];
}
return toto / data.length;
}
阵列1确实快了10倍。这是输出:
数组总时间854 矢量总时间9840
有人可以解释一下为什么吗?我已经搜索了很长一段时间,但无法弄明白。 vector方法似乎是制作向量的本地副本,但我总是认为在Java中通过引用传递的对象。
答案 0 :(得分:13)
我一直认为我们应该在Java中使用Vector,并且没有性能问题, - 错误。向量是线程安全的,因此它需要额外的逻辑(代码)来处理多个线程的访问/修改因此,它很慢。另一方面,数组不需要额外的逻辑来处理多个线程。您应该尝试ArrayList
而不是Vector
来提高速度
注意(根据您的评论):我每次运行该方法500次
这不是衡量java中性能/速度的正确方法。您至少应该进行预热,以便取消 JIT
的效果。
答案 1 :(得分:4)
是的,这是微型基准测试不良的永恒问题。 Vector
本身不是 SO 慢。
这是一个诀窍:
添加-XX:BiasedLockingStartupDelay=0
,现在添加testVector
&#34;魔法&#34;比以前快5倍!
接下来,将testVector
打包到synchronized (data)
- 现在几乎和testArray
一样快。
您基本上是在HotSpot中测量对象监视器的性能,而不是数据结构。
答案 2 :(得分:0)
简单的事情。 Vector是线程安全的,因此需要同步来添加和访问。使用ArrayList,它也是由数组备份的,但它不是线程安全的,而且更快
注意:强> 如果您事先知道ArrayList,请提供元素的大小。由于在没有初始容量的普通ArrayList中,将使用Arrays copy
进行重新调整没有初始容量性能的普通数组和ArrayList如果没有更大的元素那么会发生很大的变化
答案 3 :(得分:0)
代码不好,而不是list.get()而是在列表中使用迭代器。但阵列仍然会更快。