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

677

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

Son utilisation n'est-elle pas valable 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 c'est le CopyOnWriteArrayListcas), est-ce que c'est bien d'utiliser Vector?

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

fjsj
la source
Ils sont obsolètes, mais ils ne sont pas obsolètes.
Marquis de Lorne le

Réponses:

655

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

En règle générale, vous souhaitez synchroniser toute une séquence d'opérations. La synchronisation des opérations individuelles est à la fois moins sûre (si vous parcourez un Vector, par exemple, vous devez toujours retirer un verrou pour éviter que quelqu'un d'autre modifie la collection en même temps, ce qui provoquerait un ConcurrentModificationExceptiondans le thread d'itération) mais aussi plus lent ( pourquoi sortir une serrure à plusieurs reprises quand une fois suffira)?

Bien sûr, il a également la surcharge 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 l'a souligné M. Brian Henk , vous pouvez décorer une collection en utilisant des appels tels que Collections.synchronizedList- le fait qui Vectorcombine à la fois l'implémentation de la collection "tableau redimensionné" et le bit "synchroniser chaque opération" est un autre exemple de mauvaise conception; l'approche de la décoration permet une séparation plus nette des préoccupations.

Quant à un Stackéquivalent - je regarderais Deque/ ArrayDequepour commencer.

Jon Skeet
la source
108
"En général, vous voulez synchroniser toute une séquence d'opérations." - C'est le but! Merci!
fjsj
7
dans quelle version de java Deprecated Vector (actuellement j'utilise Java7) .Mais je ne vois jamais comme obsolète? Bye the Way nice Explication ... + 1
Samir Mangroliya
17
@Samir: Ce n'est pas officiellement obsolète - c'est juste qu'ArrayList est généralement préféré.
Jon Skeet
26
@Samir: Non, je ne vais pas essayer de prédire l'avenir.
Jon Skeet
5
simplement gr8. le vecteur n'est pas obsolète, c'est une classe héritée. Il doit y avoir une différence entre obsolète et hérité et oui, il y a stackoverflow.com/questions/2873254/…
Prashant Shilimkar
82

Le vecteur faisait partie de la version 1.0 - l'implémentation d'origine avait deux inconvénients:

1. Dénomination: les vecteurs ne sont en réalité que des listes auxquelles on peut accéder sous forme de tableaux, il aurait donc dû être appelé ArrayList(qui est le remplacement de Java 1.2 Collections Vector).

2. Concurrency: Toutes les get(), set()méthodes sont synchronized, de sorte que vous ne pouvez pas avoir un contrôle plus fin sur la synchronisation.

Il n'y a pas beaucoup de différence entre ArrayListet Vector, mais vous devez utiliser ArrayList.

À partir du document API.

Depuis la plate-forme Java 2 v1.2, cette classe a été mise à niveau pour implémenter l'interface List, ce qui en fait un membre de Java Collections Framework. Contrairement aux nouvelles implémentations de collection, Vector est synchronisé.

Justin
la source
Des listes accessibles en tant que tableaux? ArrayList n'est pas un nom très court ou accrocheur, ce qui pourrait être la raison pour laquelle le vecteur est utilisé ailleurs (par exemple la STL).
dhardy
6
@dhardy List avec un tableau comme implémentation sous-jacente. Il y a ArrayList, LinkedListetc., qui implémentent tous l'interface List, donc si vous voulez utiliser les Listméthodes sans avoir à connaître l'implémentation sous-jacente, vous pouvez simplement prendre un Listcomme paramètre pour les méthodes, etc. Il en va de même pour les implémenteurs de Mapetc. Pendant ce temps, C ++ a une std::arrayclasse, qui n'est qu'un remplacement basé sur un modèle pour les tableaux de longueur statique de style C.
JAB
41

Outre les réponses déjà énoncées sur l'utilisation de Vector, Vector a également un tas de méthodes autour de l'énumération et de la récupération des éléments qui sont différentes de l'interface List, et les développeurs (en particulier ceux qui ont appris Java avant 1.2) peuvent avoir tendance à les utiliser s'ils sont dans le 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 provoquer des problèmes, et étant donné que Vector peut être choisi pour sa synchronisation - avec l'accès associé à partir 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 de List différente.

Yishai
la source
14

Vous pouvez utiliser la méthode synchronizedCollection / List dans java.util.Collectionpour obtenir une collection thread-safe à partir d'une collection non thread-safe.

Brian Henk
la source
2
pourquoi c'est mieux que le vecteur?
fjsj
8
Comme Jon l'a mentionné, Vector ne fonctionnera pas aussi bien, et cette méthode vous permet de choisir quand c'est une bonne idée de faire la synchronisation. C'est totalement un problème de conception. Vous devez utiliser ArrayList sur Vector car vous devez utiliser par défaut un accès non synchronisé.
Brian Henk
Comment cela répond-il à la question?
Marquis de Lorne
8

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

Cependant, il hérite de bien plus que cela. Le fait que java.util.Stack extends java.util.Vectorc'est une erreur dans la conception orientée objet. Les puristes noteront qu'il propose également de nombreuses méthodes au-delà des opérations traditionnellement associées à une pile (à savoir: push, pop, peek, size). Il est également possible de le faire search, elementAt, setElementAt, remove, et bien d' autres opérations d'accès aléatoire. C'est essentiellement à l'utilisateur de s'abstenir d'utiliser les opérations hors pile deStack .

Pour ces raisons de performances et de conception OOP, JavaDoc forjava.util.Stack recommandeArrayDeque comme remplacement naturel. (Un deque est plus qu'une pile, mais au moins il se limite à manipuler les deux extrémités, plutôt qu'à offrir un accès aléatoire à tout.)

200_success
la source