为啥 Java Vector(和 Stack)类被认为已过时或不推荐使用?
Posted
技术标签:
【中文标题】为啥 Java Vector(和 Stack)类被认为已过时或不推荐使用?【英文标题】:Why is Java Vector (and Stack) class considered obsolete or deprecated?为什么 Java Vector(和 Stack)类被认为已过时或不推荐使用? 【发布时间】:2010-11-26 01:20:10 【问题描述】:为什么 Java Vector 被视为遗留类、已过时或已弃用?
在处理并发时它的使用是否有效?
如果我不想手动同步对象而只想使用线程安全的集合而不需要制作底层数组的新副本(如CopyOnWriteArrayList
所做的那样),那么使用@987654322 可以吗@?
Stack
是Vector
的子类,我应该用什么来代替它?
【问题讨论】:
它们已过时,但并未弃用。 【参考方案1】:您可以使用java.util.Collection
中的synchronizedCollection/List 方法从非线程安全的集合中获取线程安全的集合。
【讨论】:
为什么这比vector好? 正如 Jon 所提到的,Vector 的性能不会那么好,并且此方法允许您选择何时进行同步是个好主意。它完全是一个设计问题。您应该使用 ArrayList 而不是 Vector,因为您应该默认使用非同步访问。 这如何回答这个问题?【参考方案2】:Vector
同步每个单独的操作。这几乎不是你想做的。
通常您希望同步整个操作序列。同步单个操作都不太安全(例如,如果您迭代 Vector
,您仍然需要锁定以避免其他任何人同时更改集合,这将导致 ConcurrentModificationException
在迭代中线程)但也更慢(为什么一次就足够了,为什么要反复取出锁)?
当然,它也有锁定的开销,即使你不需要。
基本上,在大多数情况下,这是一种非常有缺陷的同步方法。正如 Brian Henk 先生 指出的那样,您可以使用诸如 Collections.synchronizedList
之类的调用来装饰集合 - 事实上Vector
将“调整大小的数组”集合实现与“同步每个操作”结合在一起bit 是另一个糟糕设计的例子;装饰方法可以更清晰地分离关注点。
至于 Stack
等效项 - 我会先查看 Deque
/ArrayDeque
。
【讨论】:
"通常您希望同步整个操作序列。" - 这就是我想说的!谢谢! 在哪个版本的 Java 中弃用了向量(目前我使用的是 Java7)。但我从未将其视为弃用?拜拜好解释...+1 @Samir:它没有被官方弃用——只是 ArrayList 通常是首选。 @Samir:不,我不会试图预测未来。 简单的 gr8. vector 没有被弃用,它是一个遗留类。弃用和遗留之间一定有区别,是的,见***.com/questions/2873254/…【参考方案3】:Vector 是 1.0 的一部分——最初的实现有两个缺点:
1.命名:向量实际上只是可以作为数组访问的列表,所以它应该被称为ArrayList
(这是Vector
的Java 1.2 Collections替代品)。
2。并发:所有get()
、set()
方法都是synchronized
,所以你不能对同步进行细粒度的控制。
ArrayList
和Vector
没有太大区别,但你应该使用ArrayList
。
来自 API 文档。
从 Java 2 平台 v1.2 开始,此 类被改装以实施 列表接口,使其成为 Java 集合框架。不像 新的集合实现, 向量已同步。
【讨论】:
可以作为数组访问的列表? ArrayList 不是一个很短或很吸引人的名字,这可能就是为什么在其他地方(例如 STL)使用 vector 的原因。 @dhardy 以数组作为其底层实现的列表。有ArrayList
、LinkedList
等,它们都实现了接口List
,所以如果你想使用List
方法而不必知道底层实现实际上是什么,你可以使用@987654333 @ 作为方法的参数等。这同样适用于Map
的实现者等等。同时,C++ 确实有一个 std::array
类,它只是 C 风格静态长度数组的基于模板的替代品。【参考方案4】:
除了已经说明的关于使用 Vector 的答案外,Vector 还有一堆与 List 接口不同的枚举和元素检索方法,开发人员(尤其是那些在 1.2 之前学习 Java 的人)可以倾向于使用它们,如果他们在代码中。尽管枚举速度更快,但它们不会检查集合是否在迭代期间被修改,这可能会导致问题,并且考虑到可能会选择 Vector 进行同步 - 伴随着来自多个线程的访问,这使得它成为一个特别有害的问题。使用这些方法还会将大量代码与 Vector 耦合,因此不容易用不同的 List 实现替换它。
【讨论】:
【参考方案5】:java.util.Stack
继承了java.util.Vector
的同步开销,这通常是不合理的。
不过,它继承的远不止这些。 java.util.Stack extends java.util.Vector
是面向对象设计中的一个错误。纯粹主义者会注意到,除了传统上与堆栈相关的操作(即:push、pop、peek、size)之外,它还提供了许多方法。还可以进行search
、elementAt
、setElementAt
、remove
和许多其他随机访问操作。避免使用Stack
的非堆栈操作基本上取决于用户。
出于这些性能和 OOP 设计原因,JavaDoc for java.util.Stack
建议将ArrayDeque
作为自然替代品。 (双端队列不仅仅是一个堆栈,但至少它仅限于操纵两端,而不是提供对所有内容的随机访问。)
【讨论】:
以上是关于为啥 Java Vector(和 Stack)类被认为已过时或不推荐使用?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Java Vector(和 Stack)类被认为已过时或不推荐使用?
为啥 Java Vector(和 Stack)类被认为已过时或不推荐使用?
为啥 Java Vector(和 Stack)类被认为已过时或不推荐使用?