1. 概述
在本篇文章中,我们将重点分析 Java 中 ArrayList
和 Vector
的区别。这两个类都属于 Java 集合框架,并且都实现了 java.util.List
接口。
不过,它们在实现层面存在显著差异。
2. 主要差异一览
先快速过一下两者的几个核心差异点,后续我们会逐个深入探讨:
- ✅ 线程安全(Synchronization):
Vector
是线程安全的,而ArrayList
不是。 - ✅ 扩容机制(Size Growth):当容量不足时,
Vector
会将容量翻倍,而ArrayList
只增加 50%。 - ✅ 迭代方式(Iteration):
Vector
支持Iterator
和Enumeration
两种遍历方式,而ArrayList
只支持Iterator
。 - ✅ 性能(Performance):由于同步机制的存在,
Vector
的操作通常比ArrayList
慢。 - ✅ 框架归属(Framework):
ArrayList
是集合框架的一部分,从 JDK 1.2 开始引入;而Vector
是早期版本中的遗留类。
3. Vector 简介
由于我们已经有详细的 ArrayList
教程,这里不再赘述其 API 和使用方法。我们主要来看 Vector
的一些关键特性。
简单来说,**Vector
是一个可变大小的数组**,它可以根据元素的增删自动调整容量。
创建一个 Vector
的方式如下:
Vector<String> vector = new Vector<>();
默认构造器会创建一个初始容量为 10 的空 Vector
。
添加几个元素:
vector.add("baeldung");
vector.add("Vector");
vector.add("example");
使用 Iterator
进行遍历:
Iterator<String> iterator = vector.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
// ...
}
或者使用 Enumeration
遍历:
Enumeration e = vector.elements();
while(e.hasMoreElements()) {
String element = e.nextElement();
// ...
}
接下来,我们更深入地探讨其中几个关键点。
4. 并发处理
前面我们提到 Vector
是线程安全的,而 ArrayList
不是。现在我们来看一下具体原因。
如果你查看 Vector
的源码,会发现它的大部分方法都使用了 synchronized
关键字:
public synchronized E get(int index)
✅ 这意味着同一时间只有一个线程可以访问某个 Vector
实例的方法。
⚠️ 但要注意,这种“方法级同步”并不足以保证复合操作的线程安全。比如多个步骤组合的操作(如先检查再插入),仍然需要我们自己加锁来保证原子性。
相比之下,ArrayList
的方法没有同步机制,线程安全的责任交给了开发者。
如果需要线程安全的 ArrayList
,可以使用如下替代方案:
vector.get(1); // synchronized
Collections.synchronizedList(arrayList).get(1); // 同样是同步的
或者使用更现代的并发集合类,比如:
CopyOnWriteArrayList
Collections.synchronizedList()
5. 性能对比
由于 Vector
的同步机制,它的性能通常比 ArrayList
差很多。
为了直观对比两者的性能差异,我们使用 JMH 编写了一个简单的基准测试。
5.1 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);
}
测试配置为 3 个线程,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()
的 3 倍。
5.2 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
✅ 同样地,Vector
的 contains()
方法耗时也远高于 ArrayList
。
6. 总结
本文我们详细对比了 Java 中 Vector
与 ArrayList
的区别,并深入分析了它们在并发处理、性能表现、扩容机制等方面的异同。
简单粗暴地说:
- 如果你不需要线程安全,直接用
ArrayList
。 - 如果需要线程安全,推荐使用
Collections.synchronizedList()
或CopyOnWriteArrayList
,而不是Vector
。
📌 完整代码示例可以在 GitHub 找到。