Question Pourquoi la classe Java Vector (et Stack) est-elle considérée comme obsolète ou obsolète?


Pourquoi Java Vector est-il considéré comme une classe héritée, obsolète ou obsolète?

Son utilisation n'est-elle pas valide lorsque vous travaillez avec la concurrence?

Et si je ne veux pas synchroniser manuellement les objets et que je veux juste utiliser une collection thread-safe sans avoir besoin de faire de nouvelles copies du tableau sous-jacent (comme CopyOnWriteArrayList fait), alors est-il bien d'utiliser Vector?

Qu'en est-il de Stack, qui est une sous-classe de Vector, que dois-je utiliser à la place?


612
2017-09-06 18:04


origine


Réponses:


Vector synchronise sur chaque opération individuelle. Ce n'est presque jamais ce que vous voulez faire.

Généralement, vous voulez synchroniser un séquence entière des opérations. La synchronisation des opérations individuelles est à la fois moins sûre (si vous effectuez une itération sur une Vectorpar exemple, vous devez toujours retirer une serrure pour éviter que quelqu'un d'autre ne change la collection en même temps, ce qui ConcurrentModificationException dans le thread itératif) mais aussi plus lent (pourquoi sortir une serrure à plusieurs reprises quand une fois sera suffisant)?

Bien sûr, il a également les frais généraux de verrouillage, même lorsque vous n'en avez pas besoin.

Fondamentalement, c'est une approche très imparfaite de la synchronisation dans la plupart des situations. Comme Mr Brian Henk souligné, vous pouvez décorer une collection en utilisant les appels tels que Collections.synchronizedList - le fait que Vector combine à la fois l'implémentation de la collection "resized array" avec le bit "synchronize every operation" est un autre exemple de mauvaise conception; l'approche de la décoration permet une séparation plus nette des préoccupations.

Comme pour un Stack équivalent - je regarderais Deque/ArrayDeque commencer avec.


601
2017-09-06 18:07



Le vecteur faisait partie de 1.0 - la mise en œuvre originale avait deux inconvénients:

1. Nommer: les vecteurs ne sont en fait que des listes accessibles en tant que tableaux, il aurait donc dû être appelé ArrayList (qui est le remplacement des collections Java 1.2 pour Vector).

2. Concurrence: La totalité de la get(), set() les méthodes sont synchronized, donc vous ne pouvez pas avoir un contrôle fin de la synchronisation.

Il n'y a pas beaucoup de différence entre ArrayList et Vectormais vous devriez utiliser ArrayList.

À partir du document API

Depuis la plate-forme Java 2 v1.2, cette   classe a été modernisé pour mettre en œuvre la   Liste l'interface, en faisant un membre de   le framework de collections Java. contrairement à   les nouvelles implémentations de collection,   Le vecteur est synchronisé.


74
2017-09-06 18:12



Outre les réponses déjà mentionnées sur l'utilisation de Vector, Vector propose également un ensemble de méthodes de numérotation et de récupération d'éléments différentes de celles de List. Les développeurs (en particulier ceux qui ont appris Java avant 1.2) ont tendance à les utiliser code. Bien que les énumérations soient plus rapides, elles ne vérifient pas si la collection a été modifiée pendant l'itération, ce qui peut causer des problèmes, et étant donné que Vector pourrait être choisi pour sa synchronisation - avec l'accès de plusieurs threads, cela en fait un problème particulièrement pernicieux. L'utilisation de ces méthodes couple également beaucoup de code à Vector, de sorte qu'il ne sera pas facile de le remplacer par une implémentation List différente.


40
2017-09-06 20:53



Vous pouvez utiliser le synchronizedCollection / List méthode sur java.util.Collection pour obtenir une collection sûre de thread à partir d'un non-thread sûr.


14
2017-09-06 18:07



java.util.Stack hérite de la surcharge de synchronisation de java.util.Vector, ce qui n'est généralement pas justifié.

Il hérite beaucoup plus que cela, cependant. Le fait que java.util.Stack extends java.util.Vector est une erreur dans la conception orientée objet. Les puristes remarqueront qu'il offre aussi beaucoup de méthodes au-delà des opérations traditionnellement associées à une pile (à savoir: pousser, pop, peek, taille). Il est aussi possible de faire search, elementAt, setElementAt, remove, et de nombreuses autres opérations à accès aléatoire. C'est essentiellement à l'utilisateur de s'abstenir d'utiliser les opérations de non-pile de Stack.

Pour ces raisons de performance et de conception de POO, le JavaDoc pour java.util.Stack recommande ArrayDeque comme le remplacement naturel. (Une deque est plus qu'une pile, mais au moins c'est limité à manipuler les deux extrémités, plutôt que d'offrir un accès aléatoire à tout.)


4
2018-02-12 21:04