Why is Java Vector (and Stack) class considered obsolete or deprecated?
Asked Answered
C

5

745

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 Vector?

What about Stack, which is a subclass of Vector, what should I use instead of it?

Counterpart answered 6/9, 2009 at 18:4 Comment(1)
They are obsolete, but they are not deprecated.Kamat
J
718

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 Deque/ArrayDeque to start with.

Jeffery answered 6/9, 2009 at 18:7 Comment(33)
"Generally you want to synchronize a whole sequence of operations." - That is the point! Thanks!Counterpart
in which version of java Deprecated Vector (Currently i used Java7).But I never see as a Deprecated? Bye the Way nice Explanation ...+1Leverrier
@Samir: It's not officially deprecated - it's just that ArrayList is generally preferred.Jeffery
can you tell me, in Future it happens ?Leverrier
@Samir: No, I'm not going to try to predict the future.Jeffery
@Jon Thanks for the explanation. One minor correction - the statement "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" is only partially correct - the iterator will throw a ConcurrentModificationException to avoid unpredictable behaviour if this occurs.Whisenant
@Alex: Well, my point was that you synchronize to avoid the consequences of another thread trying to do so. Will clarify.Jeffery
@Alex: The iterator will try to throw an exception. It's not guaranteed, though. The docs basically say "it's just to help detect bugs. Don't rely on it."Clariceclarie
simply gr8. vector is not deprecated its a legacy class.There must be difference between deprecated and legacy and yes there is see #2873754Orthopedic
Is there any situation where we actually need Vector to be used??Baal
@RajaAsthana: Well you might be interoperating with another API which uses it. I can't remember the last time I saw it in fresh code though.Jeffery
I do see a lot of code especially while adding errors like errorVector.add("invalid name"). Do we need to avoid this?Baal
@RajaAsthana: That really depends on the context. Where do you see all this code? Is it within some legacy codebase?Jeffery
@RajaAsthana: Then that's why you're seeing it, basically.Jeffery
@JonSkeet Last time I see Vector in code is in some example code in "Beginning JSP, JSF and Tomcat" Copyright © 2012 by Giulio Zambon. I am reading it right now. Now, after reading your post I wonder why is he still using it? Especially as he instructs at beginning of the book installing Java 7 SDK (and Tomcat 7). As for code itself he is using it because of synchronization...Bittencourt
@Nenad: I can't really answer that - but it's not what I'd do if I were writing such a book.Jeffery
Vector has the advantage of a short catchy name and its entrenchment in C++, which many programmers started out with. Outside of (inefficient) built in synchronization with Vector, you should be able to do anything with ArrayList you could do with Vector, and generally do it faster.Spiniferous
i never understood why there are people who call some parts of some API "dead" or "legacy" just because it might be inefficient. NEWSFLASH : almost all algorithms out there can be optimized, quite a lot are inefficient - yet noone calls it "dead". Efficiency isnt important anymore, we are in the 21st century so unless you're writing high-performance embedded software for space-shuttles (well, the successor) there is no point in ranting against API like that -- and even then : software engineers simply choose some alternative, they dont rant but dont worry about that just yet :)Taxidermy
@specializt: I think it's entirely reasonable to call it a legacy API if there's an alternative which is clearly better in most situations. Not only is Vector less efficient in terms of synchronizing unnecessarily, but by doing that synchronization it can give the illusion of being thread-safe to users who are new to threading and think that synchronizing each operation is sufficient to make it safe to use arbitrarily across threads. I'm still very happy to recommend moving from Vector to ArrayList in almost all cases.Jeffery
that doesnt make any sense -- its reasonable to call something "legacy" if there are better alternatives? You might want to think about that again .... with that reasoning pretty much anything in existence is "legacy"Taxidermy
@specializt: Nope, I don't think so. Searching for "define:legacy", the relevant adjective for computing states: "denoting or relating to software or hardware that has been superseded but is difficult to replace because of its wide use." That sounds pretty similar to what I said. Note that "better in most situations" is a pretty high bar - while LinkedList<T> is better than ArrayList<T> in some situations, the reverse is often true - neither effectively deprecates the other.Jeffery
@specializt: Also, from the JLS 9.6.4.6: "A program element annotated @Deprecated is one that programmers are discouraged from using, typically because it is dangerous, or because a better alternative exists." (Yes I'm aware that deprecated and legacy are not the same word, but they're often used somewhat-synonymously here. Not that Vector is officially deprecated, mind you... just like Date and Calendar aren't, but I wouldn't want to use those in new development either.)Jeffery
.. so it also is deprecated because you dont want to use it. Roight.Taxidermy
@specializt: I think at this stage we'll have to agree to disagree.Jeffery
For concurrency concern we can use java Concurrent package. However we can write code which access the collection in a non Thread-Safe manner.Gujarati
@Jon Thanks for the good answer. "As for a Stack equivalent - I'd look at Deque/ArrayDeque to start with." Does Stack also have synchronized methods as its superclass Vector? Should we replace Stack with Collections.synchronizedList applying to Deque/ArrayDeque?Boracic
@Ben: I'd expect any calls in Stack to go via the superclass methods anyway, but I'd have to check to be sure.Jeffery
@Taxidermy "Efficiency isnt important anymore". If efficiency were unimportant for lower-level programmers, it could't be unimportant for high-level productivity boys.Bilocular
yet again : that doesnt seem to make any sense. Efficiency isnt important for anyone anymore ... well ... maybe except for realtime-devs which work at projects for products which endanger or save human lives, probably - but thats a pretty small subgroup of people. Shaving off a few CPU cycles is a thing of the distant past - get over it already. Yes, we all know that you love to do it but it simply is unneccessary for product development; you can insert an optimization iteration after release if you're so desperate to make it faster.Taxidermy
@Taxidermy It can be unimportant in the higher levels. If you develop a REST service over a database in Spring, then it can be unimportant. But, if you develop Spring or Hibernate itself, or the underlying JDBC driver, or the RDBMS itself or the OS kernel under all, then not. And, even in higher level, today’s man can’t tolerate even a tiny interruption in his/her most used apps. Performance matters.Bilocular
I think you fail to understand the difference between "interruptions" to UX and (background) performance - both need not (in fact : must not) be connected - very slow background / threaded algorithms dont have any effect on UX - hence don't matter performance-wise. Unless, of course your developers are highly inexperienced and cannot (or will not) decouple UI/UX from logic. Dont worry : you'll discover that yourself in the next fee yearsTaxidermy
@Taxidermy I can't understand you. How does badly implemented concurrency and UI interruptions come here? Freezing UI graphics or slow package dependency resolution can be annoying, on their own. Anyhow, we should stop or move to the chat.Bilocular
i think you should re-do some sort of beginner-level course about programming, including concurrency and UI threads / main threads ... and maybe lookup the term "dependency resolution", you seem to mix up quite a few things here.Taxidermy
F
91

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 Vector).

2. Concurrency: All of the get(), set() methods are synchronized, so you can't have fine grained control over synchronization.

There is not much difference between ArrayList and Vector, but you should use ArrayList.

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.

Flooded answered 6/9, 2009 at 18:12 Comment(2)
Lists which can be accessed as arrays? ArrayList isn't a very short or catchy name, which might be why vector is used elsewhere (e.g. the STL).Gastroscope
@Gastroscope List with an array as its underlying implementation. There's ArrayList, LinkedList, etc., all of which implement the interface List, so if you want to utilize the List methods without having to know what the underlying implementation actually is you can just take a List as a parameter to methods, etc. The same applies for implementers of Map and so on. Meanwhile, C++ does have a std::array class, which is just a template-based replacement for C-style static length arrays.Syllabize
F
43

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.

Fuel answered 6/9, 2009 at 20:53 Comment(0)
A
15

You can use the synchronizedCollection/List method in java.util.Collection to get a thread-safe collection from a non-thread-safe one.

Antinomy answered 6/9, 2009 at 18:7 Comment(3)
why this is better than vector?Counterpart
As Jon mentioned, Vector will not perform as well, and this method allows you to choose when its a good idea to do the synchronization. Its totally a design issue. You should use ArrayList over Vector because you should default to non-synchronized access.Antinomy
How does this answer the question?Kamat
G
15

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 search, elementAt, setElementAt, remove, and many other random-access operations. It's basically up to the user to refrain from using the non-stack operations of Stack.

For these performance and OOP design reasons, the JavaDoc for java.util.Stack recommends 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.)

Garygarza answered 12/2, 2016 at 21:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.