Warum wird Java Vector als veraltete oder veraltete Legacy-Klasse betrachtet?
Ist seine Verwendung nicht gültig, wenn Sie mit Parallelität arbeiten?
Und wenn ich keine Objekte manuell synchronisieren und nur eine thread-sichere Auflistung verwenden möchte, ohne dass neue Kopien des zugrunde liegenden Arrays erstellt werden müssen (wie dies bei CopyOnWriteArrayList
der Fall ist), ist es dann in Ordnung, Vector
zu verwenden?
Was ist mit Stack
, einer Unterklasse von Vector
? Was soll ich stattdessen verwenden?
Vector
wird bei jeder einzelnen Operation synchronisiert. Das ist fast nie das, was du machen willst.
Im Allgemeinen möchten Sie eine ganze Sequenz von Operationen synchronisieren. Das Synchronisieren einzelner Vorgänge ist sowohl weniger sicher (wenn Sie beispielsweise über einen Vector
iterieren, müssen Sie immer noch eine Sperre aufheben, um zu verhindern, dass andere Personen gleichzeitig die Auflistung ändern, was zu einem ConcurrentModificationException
im iterierenden Thread führen würde) als auch langsamer (warum ein Schloss mehrmals öffnen, wenn einmal ausreicht)?
Natürlich hat es auch den Overhead zu sperren, auch wenn Sie nicht brauchen.
Grundsätzlich ist es in den meisten Situationen ein sehr fehlerhafter Ansatz zur Synchronisation. Wie Herr Brian Henk betonte, können Sie eine Sammlung mit Aufrufen wie Collections.synchronizedList
- der Tatsache dekorieren dass Vector
sowohl die Implementierung der "Resized Array" -Auflistung als auch das "Synchronize Every Operation" -Bit kombiniert, ist ein weiteres Beispiel für schlechtes Design; Der Dekorationsansatz sorgt für eine sauberere Trennung der Anliegen.
Was ein Stack
-Äquivalent betrifft, würde ich zunächst Deque
/ArrayDeque
betrachten.
Vector war Teil von 1.0 - die ursprüngliche Implementierung hatte zwei Nachteile:
1. Benennung: Vektoren sind eigentlich nur Listen, auf die als Arrays zugegriffen werden kann. Sie sollten also ArrayList
heißen (das ist der Java 1.2 Collections-Ersatz für Vector
).
2. Concurrency: Alle Methoden get()
, set()
sind synchronized
, sodass Sie die Synchronisation nicht genau steuern können.
Es gibt keinen großen Unterschied zwischen ArrayList
und Vector
, aber Sie sollten ArrayList
verwenden.
Aus dem API-Dokument.
Ab der Java 2-Plattform v1.2 wurde diese Klasse zur Implementierung der List-Schnittstelle nachgerüstet, sodass sie Mitglied des Java Collections Framework ist. Im Gegensatz zu den neuen Auflistungsimplementierungen wird Vector synchronisiert.
Neben den bereits erwähnten Antworten zur Verwendung von Vector bietet Vector auch eine Reihe von Methoden zum Aufzählen und Abrufen von Elementen, die sich von der List-Oberfläche unterscheiden, und Entwickler (insbesondere diejenigen, die Java vor 1.2 gelernt haben) können dazu neigen, diese zu verwenden sie, wenn sie im Code sind. Aufzählungen sind zwar schneller, sie überprüfen jedoch nicht, ob die Auflistung während der Iteration geändert wurde, was zu Problemen führen kann. Angesichts der Tatsache, dass Vector möglicherweise für die Synchronisierung ausgewählt wurde und der damit verbundene Zugriff von mehreren Threads aus erfolgt, ist dies ein besonders gefährliches Problem. Durch die Verwendung dieser Methoden wird auch viel Code an Vector gekoppelt, sodass es nicht einfach ist, ihn durch eine andere List-Implementierung zu ersetzen.
Sie können die synchronizedCollection/List -Methode für Java.util.Collection
verwenden, um eine thread-sichere Auflistung von einer nicht thread-sicheren abzurufen.
Java.util.Stack
erbt den Synchronisationsaufwand von Java.util.Vector
, der normalerweise nicht gerechtfertigt ist.
Es erbt jedoch noch viel mehr. Die Tatsache, dass Java.util.Stack extends Java.util.Vector
ein Fehler im objektorientierten Design ist. Puristen werden feststellen, dass es auch viele Methoden bietet, die über die traditionell mit einem Stapel verbundenen Operationen hinausgehen (nämlich Push, Pop, Peek, Size). Es ist auch möglich, search
, elementAt
, setElementAt
, remove
und viele andere Operationen mit wahlfreiem Zugriff auszuführen. Grundsätzlich ist es Sache des Benutzers, die Nicht-Stack-Operationen von Stack
zu unterlassen.
Aus diesen Leistungs- und OOP Entwurfsgründen empfiehlt JavaDoc for Java.util.Stack
ArrayDeque
als natürlichen Ersatz. (Eine Deque ist mehr als ein Stapel, aber zumindest ist sie darauf beschränkt, die beiden Enden zu manipulieren, anstatt auf alles willkürlich zuzugreifen.)