为什么Java Vector(和Stack)类被视为过时或过时的?


676

为什么Java Vector被认为是旧的类,已经过时或过时了?

使用并发时,使用它无效吗?

而且,如果我不想手动同步对象,而只想使用线程安全的集合而不需要创建基础数组的新副本(也是CopyOnWriteArrayList如此),那么使用它就可以了Vector吗?

怎么样Stack,这是一个子类Vector,我应该怎么用,而不是它?


它们已过时,但不被弃用。
user207421 '19

Answers:


654

Vector在每个单独的操作上同步。那几乎从来不是你想要做的。

通常,您要同步整个操作序列。同步单个操作既不安全(Vector例如,如果对进行迭代,则仍然需要锁,以避免其他人同时更改集合,这将导致ConcurrentModificationException迭代线程中的错误),但同步速度也较慢(为什么一次就够了就反复拿出锁)?

当然,即使您不需要时,它也具有锁定的开销。

基本上,在大多数情况下,这是一种非常有缺陷的同步方法。正如Brian Henk先生指出的那样,您可以使用以下调用来装饰集合:Collections.synchronizedList- Vector将“调整大小的数组”集合实现与“同步每个操作”位结合在一起的事实是设计不良的另一个例子;装饰方法使关注点更清晰地分离。

至于Stack等效项-我会先看Deque/ ArrayDeque


108
“通常,您要同步整个操作序列。” - 这就是重点!谢谢!
fjsj

7
在哪个版本的Java Deprecated Vector中(当前我使用Java7)。但是我从来没有看到过Deprecated?再见的方式很好的解释... + 1
萨米尔·曼格罗里亚

17
@Samir:尚未正式弃用-只是通常首选ArrayList。
乔恩·斯基特

26
@Samir:不,我不会尝试预测未来。
乔恩·斯基特

5
只是gr8。矢量不会被弃用其遗留class.There必须弃用,遗产,是的,有看的区别stackoverflow.com/questions/2873254/...
PRASHANT Shilimkar

82

Vector是1.0的一部分-原始实现有两个缺点:

1.命名:向量实际上只是可以作为数组访问的列表,因此应该调用它ArrayList(这是Java 1.2 Collections的替代品Vector)。

2.并发性:所有get()set()方法都是synchronized,因此您无法对同步进行精细控制。

ArrayList和之间没有太大区别Vector,但是您应该使用ArrayList

来自API文档。

从Java 2平台v1.2开始,对该类进行了改进以实现List接口,使其成为Java Collections Framework的成员。与新的集合实现不同,Vector是同步的。


可以作为数组访问的列表?ArrayList不是一个简短的名称,这可能就是为什么在其他地方(例如STL)使用vector的原因。
dhardy 2013年

6
@dhardy列出数组作为其基础实现。还有ArrayListLinkedList等等,所有这些都实现这个接口List,所以如果你想使用的List方法,而无需知道底层的实现实际上是你可以采取一个List作为参数传递给方法,等等。这同样适用于工作的执行Map等等。同时,C ++确实有一个std::array类,该类只是基于模板的C样式静态长度数组的替代。
JAB

41

除了已经说过的使用Vector的答案外,Vector还具有许多围绕List和List的枚举和元素检索方法,并且开发人员(尤其是那些在1.2之前学习过Java的人)可以倾向于使用它们。码。尽管枚举速度更快,但它们不会检查迭代期间是否对集合进行了修改,这可能会导致问题,并且考虑到可能会选择Vector进行同步-伴随有来自多个线程的访问,这使其成为一个特别有害的问题。这些方法的使用还将大量代码与Vector耦合在一起,因此用其他List实现替换它并不容易。


14

您可以在其中使用syncedCollection / List方法java.util.Collection从非线程安全的集合中获取线程安全的集合。


2
为什么这比矢量更好?
fjsj 2009年

8
正如乔恩(Jon)所述,Vector的性能不佳,并且该方法允许您选择何时进行同步是一个好主意。这完全是一个设计问题。您应该在Vector上使用ArrayList,因为您应该默认为非同步访问。
Brian Henk

这如何回答这个问题?
user207421 '19

8

java.util.Stack继承的同步开销java.util.Vector,通常是不合理的。

但是,它继承的更多。这java.util.Stack extends java.util.Vector是面向对象设计中的错误。纯粹主义者将注意到,除了传统上与堆栈相关的操作(即:推入,弹出,窥视,大小)之外,它还提供了许多方法。它也可以做到searchelementAtsetElementAtremove,和其他许多随机存取操作。基本上,用户应避免使用的非堆栈操作Stack

由于这些性能和OOP设计原因,推荐使用JavaDocjava.util.StackArrayDeque作为自然替代品。(双端队列不仅是堆栈,但至少限于操作两端,而不是提供对所有内容的随机访问。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.