Vector 是 Java 中一个经典的集合类,它是动态数组 的实现,位于 java.util 包中。虽然在现代 Java 开发中它已不是首选,但理解它的特性和历史背景仍然很重要。
Java的 Vector 类拥有一个清晰的继承与实现层次。它的完整声明如下:
java
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
下面这个表格可以帮你快速了解 Vector 的整个"家谱"结构。
| 类别 | 类/接口 | 与 Vector 的关系 |
核心作用 |
|---|---|---|---|
| 父类 | AbstractList |
继承 | 提供了 List 接口的骨架实现,如 get、add、remove 等方法的基本逻辑。 |
| 核心接口 | List |
实现 | 定义了有序集合(序列)的标准契约,是 Vector 作为动态数组的核心依据。 |
| 标记接口 | RandomAccess |
实现 | 标记接口 ,表明 Vector 支持高效(常数时间)的随机访问(如 get(i))。 |
Cloneable |
实现 | 标记接口 ,表明 Vector 实例可以被 clone() 方法复制。 |
|
Serializable |
实现 | 标记接口 ,表明 Vector 可以被序列化(可转化为字节流用于网络传输或持久化存储)。 |
整体架构图
从 Object 类开始的完整单继承链是:Object → AbstractCollection → AbstractList → Vector。
接口与实现的要点解析
了解这些接口和父类,能帮助你理解 Vector 的行为:
-
线程安全的基石 :虽然线程安全不是通过某个特定接口定义的,但它是
Vector区别于ArrayList最关键的实现细节。它的核心操作方法(如add,remove,get)都使用synchronized关键字修饰,保证了多线程环境下的数据安全,但也带来了性能开销。 -
RandomAccess的实际影响 :实现这个标记接口意味着像Collections.binarySearch()这样的算法在处理Vector时,会优先使用效率更高的基于索引的随机访问,而不是迭代器。
核心特性
1. 同步/线程安全
Vector 的所有主要方法都使用 synchronized 关键字修饰,因此是线程安全的。
java
// 线程安全示例
Vector<String> vector = new Vector<>();
// 以下操作在多线程环境下是安全的
vector.add("Item1");
vector.get(0);
2. 动态扩容
当容量不足时,Vector 会自动增长:
-
默认初始容量:10
-
默认增长策略:容量翻倍(可自定义)
java
Vector<Integer> v = new Vector<>(5, 3); // 初始容量5,每次增加3
for (int i = 0; i < 10; i++) {
v.add(i);
System.out.println("Size: " + v.size() + ", Capacity: " + v.capacity());
}
3. 遗留类
Vector 是 Java 1.0 就存在的类,后来为了更好的集合框架设计,在 Java 1.2 中引入了 Collection 框架。
与 ArrayList 的对比
| 特性 | Vector | ArrayList |
|---|---|---|
| 线程安全 | 是(同步方法) | 否 |
| 性能 | 较慢(同步开销) | 较快 |
| 扩容策略 | 默认翻倍(可自定义增量) | 默认增加50% |
| 迭代器 | fail-fast(快速失败) | fail-fast |
| Java版本 | 1.0 | 1.2 |
基本用法示例
java
import java.util.*;
public class VectorExample {
public static void main(String[] args) {
// 创建 Vector
Vector<String> fruits = new Vector<>();
// 添加元素
fruits.add("Apple");
fruits.add("Banana");
fruits.addElement("Cherry"); // 遗留方法
// 获取元素
System.out.println(fruits.get(0)); // Apple
System.out.println(fruits.elementAt(1)); // 遗留方法: Banana
// 遍历
// 1. 使用迭代器
Iterator<String> it = fruits.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
// 2. 使用 Enumeration(遗留方式)
Enumeration<String> en = fruits.elements();
while (en.hasMoreElements()) {
System.out.println(en.nextElement());
}
// 容量相关操作
System.out.println("Size: " + fruits.size()); // 当前元素数量
System.out.println("Capacity: " + fruits.capacity()); // 当前容量
fruits.ensureCapacity(20); // 确保最小容量
fruits.trimToSize(); // 将容量调整为当前大小
}
}
线程安全示例
java
import java.util.Vector;
public class ThreadSafeExample {
private static Vector<Integer> vector = new Vector<>();
public static void main(String[] args) throws InterruptedException {
// 创建多个线程同时修改 Vector
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
vector.add(i);
}
});
Thread t2 = new Thread(() -> {
for (int i = 1000; i < 2000; i++) {
vector.add(i);
}
});
t1.start();
t2.start();
t1.join();
t2.join();
// 不会出现并发问题
System.out.println("Vector size: " + vector.size()); // 应该是2000
}
}
现代替代方案
1. 使用 ArrayList + 同步包装
java
// 替代 Vector 的线程安全方案
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
// 或者在并发场景下使用
List<String> concurrentList = new CopyOnWriteArrayList<>();
2. 并发集合类
java
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ConcurrentLinkedQueue;
// 高并发读取场景
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
// 并发队列
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
使用建议
使用 Vector 的场景
-
维护遗留代码
-
简单的多线程共享集合(但现代方案更好)
避免使用 Vector 的场景
-
新开发的项目
-
单线程环境(使用
ArrayList) -
高并发环境(使用
java.util.concurrent包中的类)
重要方法总结
java
// 添加元素
add(E e) // 添加元素
addElement(E obj) // 遗留方法
insertElementAt(E obj, int index)
// 获取元素
get(int index)
elementAt(int index) // 遗留方法
firstElement()
lastElement()
// 删除元素
remove(int index)
removeElement(Object obj)
clear()
// 容量管理
ensureCapacity(int minCapacity)
trimToSize()
setSize(int newSize) // 可能填充null或截断
// 搜索
contains(Object o)
indexOf(Object o)
// 枚举器(遗留)
elements() // 返回 Enumeration
性能考虑
由于 Vector 的方法都是同步的,在多线程竞争激烈的情况下,性能会受到影响。现代 Java 提供了更精细的并发控制机制:
java
// 更好的多线程方案
List<String> list = new ArrayList<>();
// 只在必要时同步
synchronized(list) {
list.add("item");
}
总结 :虽然 Vector 在 Java 历史上占有重要地位,但在现代开发中,ArrayList 和 java.util.concurrent 包中的并发集合通常是更好的选择。理解 Vector 有助于维护遗留代码,但在新项目中应优先考虑更现代的替代方案。