每个人都说应该使用矢量因为性能(导致Vector在每次操作和东西之后同步).我写了一个简单的测试:
import java.util.ArrayList; import java.util.Date; import java.util.Vector; public class ComparePerformance { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<Integer>(); Vector<Integer> vector = new Vector<Integer>(); int size = 10000000; int listSum = 0; int vectorSum = 0; long startList = new Date().getTime(); for (int i = 0; i < size; i++) { list.add(new Integer(1)); } for (Integer integer : list) { listSum += integer; } long endList = new Date().getTime(); System.out.println("List time: " + (endList - startList)); long startVector = new Date().getTime(); for (int i = 0; i < size; i++) { vector.add(new Integer(1)); } for (Integer integer : list) { vectorSum += integer; } long endVector = new Date().getTime(); System.out.println("Vector time: " + (endVector - startVector)); } }
结果如下:
List time: 4360 Vector time: 4103
解决方法
你写了一个天真的微基准. JVM上的微博技术是一项非常棘手的业务,它甚至不容易列举所有陷阱,但这里有一些经典的:
>你必须热身代码;
>你必须控制垃圾收集暂停;
> System.currentTimeMillis是不精确的,但你似乎并不知道这个方法(你的新Date().getTime()是等效的,但更慢).
如果您想要正确执行此操作,请查看Oracle的jmh工具或Google的Caliper.
我的测试结果
由于我有兴趣自己看这些数字,这里是jmh的输出.一,测试代码:
public class Benchmark1 { static Integer[] ints = new Integer[0]; static { final List<Integer> list = new ArrayList(asList(1,2,3,4,5,6,7,8,9,10)); for (int i = 0; i < 5; i++) list.addAll(list); ints = list.toArray(ints); } static List<Integer> intList = Arrays.asList(ints); static Vector<Integer> vec = new Vector<Integer>(intList); static List<Integer> list = new ArrayList<Integer>(intList); @GenerateMicroBenchmark public Vector<Integer> testVectorAdd() { final Vector<Integer> v = new Vector<Integer>(); for (Integer i : ints) v.add(i); return v; } @GenerateMicroBenchmark public long testVectorTraverse() { long sum = (long)Math.random()*10; for (int i = 0; i < vec.size(); i++) sum += vec.get(i); return sum; } @GenerateMicroBenchmark public List<Integer> testArrayListAdd() { final List<Integer> l = new ArrayList<Integer>(); for (Integer i : ints) l.add(i); return l; } @GenerateMicroBenchmark public long testArrayListTraverse() { long sum = (long)Math.random()*10; for (int i = 0; i < list.size(); i++) sum += list.get(i); return sum; } }
结果如下:
testArrayListAdd 234.896 ops/msec testVectorAdd 274.886 ops/msec testArrayListTraverse 1718.711 ops/msec testVectorTraverse 34.843 ops/msec
请注意以下事项:
>在……添加方法我正在创建一个新的本地集合. JIT编译器使用这个事实并省略了对Vector方法的锁定 – 因此几乎相同的性能;
>在……遍历方法我正在从全球集合中读取;锁不能被省略,这就是Vector的真正性能损失显示的地方.
这样做的主要内容应该是:JVM上的性能模型非常复杂,有时甚至是不稳定的.从微基准测量推断,即使在完全适当的情况下完成,也可能导致对生产系统性能的危险错误预测.