Warum wird die Java Vector- (und Stack-) Klasse als veraltet oder veraltet angesehen?

677

Warum wird Java Vector als Legacy-Klasse angesehen, veraltet oder veraltet?

Ist seine Verwendung bei der Arbeit mit Parallelität nicht gültig?

Und wenn ich Objekte nicht manuell synchronisieren und nur eine thread-sichere Sammlung verwenden möchte, ohne (wie CopyOnWriteArrayListauch) neue Kopien des zugrunde liegenden Arrays erstellen zu müssen, ist die Verwendung dann in Ordnung Vector?

Was ist mit Stack, was ist eine Unterklasse von Vector, was soll ich stattdessen verwenden?

fjsj
quelle
Sie sind veraltet, aber nicht veraltet.
Marquis von Lorne

Antworten:

655

Vectorsynchronisiert bei jeder einzelnen Operation. Das ist fast nie das, was du tun willst.

Im Allgemeinen möchten Sie eine ganze Abfolge von Vorgängen synchronisieren . Das Synchronisieren einzelner Vorgänge ist sowohl weniger sicher (wenn Sie beispielsweise über eine iterieren Vector, müssen Sie dennoch eine Sperre aufheben, um zu vermeiden, dass andere Personen gleichzeitig die Sammlung ändern, was zu einem ConcurrentModificationExceptionim iterierenden Thread führen würde) als auch langsamer ( Warum wiederholt ein Schloss schließen, wenn einmal genug ausreicht?

Natürlich hat es auch den Aufwand, zu sperren, selbst wenn Sie nicht müssen.

Grundsätzlich ist es in den meisten Situationen ein sehr fehlerhafter Ansatz zur Synchronisation. Wie Herr Brian Henk betonte, können Sie eine Sammlung mithilfe folgender Aufrufe dekorieren Collections.synchronizedList: Die Tatsache, dass Vectorsowohl die Implementierung der Sammlung "Resized Array" als auch das Bit "Jede Operation synchronisieren" kombiniert werden, ist ein weiteres Beispiel für schlechtes Design. Der Dekorationsansatz sorgt für eine sauberere Trennung der Anliegen.

Was ein StackÄquivalent betrifft - ich würde es mir ansehen Deque/ ArrayDequeanfangen.

Jon Skeet
quelle
108
"Im Allgemeinen möchten Sie eine ganze Abfolge von Vorgängen synchronisieren." - Das ist der Punkt! Vielen Dank!
fjsj
7
in welcher Version von Java Deprecated Vector (Derzeit habe ich Java7 verwendet). Aber ich sehe nie als veraltet? Bye the Way nice Erklärung ... + 1
Samir Mangroliya
17
@ Samir: Es ist nicht offiziell veraltet - es ist nur so, dass ArrayList im Allgemeinen bevorzugt wird.
Jon Skeet
26
@ Samir: Nein, ich werde nicht versuchen, die Zukunft vorherzusagen.
Jon Skeet
5
einfach gr8. Vektor ist nicht veraltet, es ist eine Legacy-Klasse. Es muss einen Unterschied zwischen veraltet und Legacy geben und ja, es gibt siehe stackoverflow.com/questions/2873254/…
Prashant Shilimkar
82

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, daher sollte sie aufgerufen worden sein ArrayList(was der Ersatz für Java 1.2-Sammlungen ist Vector).

2. Concurrency: Alle die get(), set()Methoden sind synchronized, so dass Sie nicht eine genaue Kontrolle über die Synchronisation gekörnt haben können.

Es gibt keinen großen Unterschied zwischen ArrayListund Vector, aber Sie sollten verwenden ArrayList.

Aus dem API-Dokument.

Ab der Java 2-Plattform v1.2 wurde diese Klasse nachgerüstet, um die List-Schnittstelle zu implementieren, sodass sie Mitglied des Java Collections Framework ist. Im Gegensatz zu den neuen Sammlungsimplementierungen ist Vector synchronisiert.

Justin
quelle
Listen, auf die als Arrays zugegriffen werden kann? ArrayList ist kein sehr kurzer oder eingängiger Name, weshalb der Vektor möglicherweise an anderer Stelle verwendet wird (z. B. die STL).
Dhardy
6
@dhardy Liste mit einem Array als zugrunde liegender Implementierung. Es gibt ArrayList, LinkedListetc., die alle die Schnittstelle implementieren List, so dass , wenn Sie die nutzen wollen ListMethoden , ohne zu wissen , was die zugrunde liegende Implementierung Sie können tatsächlich nehmen nur Listals Parameter an Methoden usw. Das gleiche gilt für Implementierer gilt von Mapund so weiter. Inzwischen hat C ++ eine std::arrayKlasse, die nur ein vorlagenbasierter Ersatz für Arrays mit statischer Länge im C-Stil ist.
JAB
41

Neben den bereits genannten Antworten zur Verwendung von Vector verfügt Vector auch über eine Reihe von Methoden zur Aufzählung und zum Abrufen von Elementen, die sich von der List-Oberfläche unterscheiden. Entwickler (insbesondere diejenigen, die Java vor 1.2 gelernt haben) können diese verwenden, wenn sie sich in der Code. Obwohl Aufzählungen schneller sind, prüfen sie nicht, ob die Sammlung 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, ist dies aufgrund des damit verbundenen Zugriffs von mehreren Threads ein besonders schädliches Problem. Durch die Verwendung dieser Methoden wird auch viel Code mit Vector gekoppelt, sodass es nicht einfach ist, ihn durch eine andere List-Implementierung zu ersetzen.

Yishai
quelle
14

Sie können die synchronizedCollection / List- Methode in verwenden java.util.Collection, um eine thread-sichere Sammlung von einer nicht thread-sicheren Sammlung abzurufen.

Brian Henk
quelle
2
Warum ist das besser als Vektor?
fjsj
8
Wie Jon erwähnt hat, funktioniert Vector nicht so gut, und mit dieser Methode können Sie auswählen, wann die Synchronisierung sinnvoll ist. Es ist total ein Designproblem. Sie sollten ArrayList over Vector verwenden, da Sie standardmäßig nicht synchronisierten Zugriff verwenden sollten.
Brian Henk
Wie beantwortet dies die Frage?
Marquis von Lorne
8

java.util.Stackerbt den Synchronisationsaufwand von java.util.Vector, der normalerweise nicht gerechtfertigt ist.

Es erbt jedoch viel mehr als das. Die Tatsache, dass dies java.util.Stack extends java.util.Vectorein Fehler im objektorientierten Design ist. Puristen werden bemerken, 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 zu tun search, elementAt, setElementAt, remove, und viele andere Schreib-Lese-Operationen. Grundsätzlich ist es Sache des Benutzers, die Nicht-Stack-Operationen von nicht zu verwenden Stack.

Aus diesen Gründen der Leistung und des OOP-Designs empfiehlt JavaDocjava.util.StackArrayDeque als natürlichen Ersatz. (Eine Deque ist mehr als ein Stapel, aber zumindest beschränkt sie sich darauf, die beiden Enden zu manipulieren, anstatt zufälligen Zugriff auf alles zu bieten.)

200_Erfolg
quelle