Vector 和 Stack:过时的 API 以及替代方案
一句话警告
Vector 和 Stack 已被废弃。它们是 JDK 1.0 的遗留代码,在性能和设计上都有问题。现代 Java 代码不应该再使用它们。
Vector vs ArrayList:有什么区别
Vector 几乎是 ArrayList 的「同步版本」:
java
// Vector:所有方法都 synchronized
public class Vector<E> {
public synchronized boolean add(E e) { ... }
public synchronized E get(int index) { ... }
public synchronized E set(int index, E e) { ... }
// ...
}
// ArrayList:方法不带 synchronized
public class ArrayList<E> {
public boolean add(E e) { ... } // 没有 synchronized
public E get(int index) { ... } // 没有 synchronized
}扩容机制也不同
| 特性 | Vector | ArrayList |
|---|---|---|
| 默认容量 | 10 | 0(首次添加时才 10) |
| 扩容倍数 | 2 倍 | 1.5 倍 |
| 线程安全 | 是(synchronized) | 否 |
Stack 的继承问题
Stack 继承自 Vector,这是设计上的一个大问题:
java
public class Stack<E> extends Vector<E> { ... }继承 Vector 意味着 Stack 拥有了 Vector 的所有方法,包括按索引访问、按位置插入等——这些「超能力」对栈来说是不应该有的。
java
Stack<String> stack = new Stack<>();
stack.push("A");
stack.push("B");
// ❌ Stack 继承自 Vector,所以这些方法也存在:
stack.get(0); // 栈不应该能按索引访问
stack.add(0, "C"); // 栈不应该能在中间插入
stack.remove(0); // 栈不应该能按索引删除一个好的设计应该是「组合优于继承」。
三种替代方案
替代 1:ArrayDeque(推荐用于栈/队列)
java
// ✅ Stack 替换为 ArrayDeque
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println("栈顶: " + stack.peek()); // 3
System.out.println("出栈: " + stack.pop()); // 3
System.out.println("栈顶: " + stack.peek()); // 2性能对比:
ArrayDeque.push/pop: ~5 ms(10 万元素)
Stack.push/pop: ~15 ms替代 2:LinkedList(需要 Queue 功能时)
java
// ✅ 队列和栈都可以用 LinkedList
Deque<String> stack = new LinkedList<>();
Deque<String> queue = new LinkedList<>();
// 作为栈
stack.push("A");
stack.pop();
// 作为队列
queue.offer("A");
queue.poll();替代 3:双端队列(JDK 6+ 的 Deque)
java
// ✅ Deque 接口,明确支持栈和队列操作
Deque<Integer> deque = new ArrayDeque<>();
// 栈操作
deque.push(1);
deque.pop();
// 队列操作
deque.offerLast(1);
deque.pollFirst();迁移指南
从 Stack 迁移到 ArrayDeque
java
// ❌ 旧代码
Stack<Order> orderStack = new Stack<>();
while (hasMoreOrders()) {
orderStack.push(processOrder());
}
// ✅ 新代码
Deque<Order> orderStack = new ArrayDeque<>();
while (hasMoreOrders()) {
orderStack.push(processOrder());
}从 Vector 迁移到 ArrayList
java
// ❌ 旧代码
Vector<String> old = new Vector<>();
old.add("a");
synchronized (old) {
for (String s : old) {
System.out.println(s);
}
}
// ✅ 新代码:单线程用 ArrayList
List<String> list = new ArrayList<>();
list.add("a");
for (String s : list) {
System.out.println(s);
}
// ✅ 多线程用 CopyOnWriteArrayList 或 synchronizedList
List<String> safe = new CopyOnWriteArrayList<>();
// 或
List<String> safe2 = Collections.synchronizedList(new ArrayList<>());什么时候还在用 Vector/Stack
坦率地说:几乎不应该用。但如果遇到遗留代码需要维护,记住:
| 场景 | 建议 |
|---|---|
| 新代码 | 永远不要用 |
| 遗留代码维护 | 找机会迁移到 ArrayDeque |
| 线程安全需求 | 用 Collections.synchronizedList 或 CopyOnWriteArrayList |
总结
| 特性 | Vector | Stack | ArrayList | ArrayDeque |
|---|---|---|---|---|
| 线程安全 | ✅ | ✅(继承自 Vector) | ❌ | ❌ |
| 性能 | 差(全局锁) | 差 | 好 | 最好 |
| 扩容倍数 | 2 倍 | 2 倍 | 1.5 倍 | 2 倍 |
| 推荐程度 | 不推荐 | 不推荐 | ✅ 推荐 | ✅ 最推荐 |
