Why is Java Vector considered a legacy class, obsolete or deprecated?
Isn’t its use valid when working with concurrency?
And if I don’t want to manually synchronize objects and just want to use a thread-safe collection without needing to make fresh copies of the underlying array (as
CopyOnWriteArrayList does), then is it fine to use
Stack, which is a subclass of
Vector, what should I use instead of it?
Vector synchronizes on each individual operation. That’s almost never what you want to do.
Generally you want to synchronize a whole sequence of operations. Synchronizing individual operations is both less safe (if you iterate over a
Vector, for instance, you still need to take out a lock to avoid anyone else changing the collection at the same time, which would cause a
ConcurrentModificationException in the iterating thread) but also slower (why take out a lock repeatedly when once will be enough)?
Of course, it also has the overhead of locking even when you don’t need to.
Basically, it’s a very flawed approach to synchronization in most situations. As Mr Brian Henk pointed out, you can decorate a collection using the calls such as
Collections.synchronizedList – the fact that
Vector combines both the “resized array” collection implementation with the “synchronize every operation” bit is another example of poor design; the decoration approach gives cleaner separation of concerns.
As for a
Stack equivalent – I’d look at
ArrayDeque to start with.
Vector was part of 1.0 — the original implementation had two drawbacks:
1. Naming: vectors are really just lists which can be accessed as arrays, so it should have been called
ArrayList (which is the Java 1.2 Collections replacement for
2. Concurrency: All of the
set() methods are
synchronized, so you can’t have fine grained control over synchronization.
There is not much difference between
Vector, but you should use
From the API doc.
As of the Java 2 platform v1.2, this
class was retrofitted to implement the
List interface, making it a member of
the Java Collections Framework. Unlike
the new collection implementations,
Vector is synchronized.
Besides the already stated answers about using Vector, Vector also has a bunch of methods around enumeration and element retrieval which are different than the List interface, and developers (especially those who learned Java before 1.2) can tend to use them if they are in the code. Although Enumerations are faster, they don’t check if the collection was modified during iteration, which can cause issues, and given that Vector might be chosen for its syncronization – with the attendant access from multiple threads, this makes it a particularly pernicious problem. Usage of these methods also couples a lot of code to Vector, such that it won’t be easy to replace it with a different List implementation.
You can use the synchronizedCollection/List method on
java.util.Collection to get a thread safe collection from a non-thread safe one.
java.util.Stack inherits the synchronization overhead of
java.util.Vector, which is usually not justified.
It inherits a lot more than that, though. The fact that
java.util.Stack extends java.util.Vector is a mistake in object-oriented design. Purists will note that it also offers a lot of methods beyond the operations traditionally associated with a stack (namely: push, pop, peek, size). It’s also possible to do
remove, and many other random-access operations. It’s basically up to the user to refrain from using the non-stack operations of
For these performance and OOP design reasons, the JavaDoc for
ArrayDeque as the natural replacement. (A deque is more than a stack, but at least it’s restricted to manipulating the two ends, rather than offering random access to everything.)