Java 中 Arraylist和vector
1. 概述
在本教程中,我们将重点关注ArrayList和Vector类之间的区别。它们都属于 Java Collections Framework 并实现了java.util.List接口。
但是,这些类在实现上存在显着差异。
2. 有什么不同?
作为快速入门,让我们介绍ArrayList和Vector的主要区别。**然后,我们将更详细地讨论一些要点:
- 同步——这两者之间的第一个主要区别。Vector是同步的,而ArrayList不是。
- 大小增长——两者之间的另一个区别是它们在达到容量时调整大小的方式。Vector的大小翻了一番。相比之下,ArrayList只增加了一半的长度
- 迭代 ——Vector可以使用Iterator和Enumeration遍历元素。**另一方面,ArrayList只能使用 Iterator。
- 性能——很大程度上是由于同步, 与ArrayList相比,Vector操作更慢
- 框架 – 此外,ArrayList是 Collections 框架的一部分,在 JDK 1.2 中引入。同时,Vector 作为遗留类存在于早期版本的 Java 中。
3. Vector
由于我们已经有一个关于*ArrayList * 的扩展指南,我们不会在这里讨论它的 API 和功能。另一方面,我们将介绍有关Vector的一些核心细节。
简单地说,Vector是 一个可调整大小的数组。当我们添加或删除元素时,它可以增长和缩小。
我们可以用典型的方式创建一个向量:
Vector<String> vector = new Vector<>();
默认构造函数创建一个初始容量为 10的空Vector。
让我们添加一些值:
vector.add("blogdemo");
vector.add("Vector");
vector.add("example");
最后,让我们使用Iterator 接口遍历这些值:
Iterator<String> iterator = vector.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
// ...
}
或者,我们可以使用 Enumeration遍历Vector:
Enumeration e = vector.elements();
while(e.hasMoreElements()) {
String element = e.nextElement();
// ...
}
现在,让我们更深入地探索它们的一些独特功能。
4. 并发
我们已经提到ArrayList和Vector在并发策略上是不同的,但让我们仔细看看。如果我们深入研究Vector的方法签名,我们会看到每个都有 synchronized 关键字:
public synchronized E get(int index)
简单地说,这意味着一次只有一个线程可以访问给定的向量。
但是,实际上,无论如何,这种操作级别的同步都需要与我们自己的复合操作同步覆盖。
所以相比之下,ArrayList采用了不同的方法。它的方法是不同步的,并且这种关注被分离到专门用于并发的类中。
例如,我们可以使用 CopyOnWriteArrayList 或 Collections.synchronizedList 来获得与 Vector类似的效果:
vector.get(1); // synchronized
Collections.synchronizedList(arrayList).get(1); // also synchronized
5. 性能
正如我们上面已经讨论过的,Vector是同步的,这会对性能产生直接影响。
要查看Vector与ArrayList操作之间的性能差异 ,让我们编写一个简单的JMH 基准 测试。
过去,我们已经研究 了ArrayList操作的时间复杂度 ,所以让我们添加Vector的测试用例。
首先,让我们测试一下*get()*方法:
@Benchmark
public Employee testGet(ArrayListBenchmark.MyState state) {
return state.employeeList.get(state.employeeIndex);
}
@Benchmark
public Employee testVectorGet(ArrayListBenchmark.MyState state) {
return state.employeeVector.get(state.employeeIndex);
}
我们将配置 JMH 以使用三个线程和 10 次预热迭代。 并且,让我们以纳秒级报告每次操作的平均时间:
Benchmark Mode Cnt Score Error Units
ArrayListBenchmark.testGet avgt 20 9.786 ± 1.358 ns/op
ArrayListBenchmark.testVectorGet avgt 20 37.074 ± 3.469 ns/op
我们可以看到 ArrayList#get的工作速度大约是Vector#get的三倍。**
现在,让我们比较一下*contains()*操作的结果:
@Benchmark
public boolean testContains(ArrayListBenchmark.MyState state) {
return state.employeeList.contains(state.employee);
}
@Benchmark
public boolean testContainsVector(ArrayListBenchmark.MyState state) {
return state.employeeVector.contains(state.employee);
}
并将结果打印出来:
Benchmark Mode Cnt Score Error Units
ArrayListBenchmark.testContains avgt 20 8.665 ± 1.159 ns/op
ArrayListBenchmark.testContainsVector avgt 20 36.513 ± 1.266 ns/op
正如我们所见,对于contains()操作,Vector的执行时间比ArrayList长得多 。