web-dev-qa-db-fra.com

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 une 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 le fait CopyOnWriteArrayList, alors c'est bien d'utiliser Vector?

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

653
fjsj

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

Généralement, vous souhaitez synchroniser une séquence complète . La synchronisation des opérations individuelles est à la fois moins sûre (si vous effectuez une itération sur un Vector, par exemple, vous devez toujours désactiver un verrou pour éviter que quiconque ne modifie la collection en même temps, ce qui provoquerait un ConcurrentModificationException dans le fil de discussion itératif) mais aussi plus lent (pourquoi enlever un verrou à plusieurs reprises alors qu'une seule fois suffira)?

Bien sûr, cela entraîne également des frais généraux de verrouillage, même lorsque vous n'en avez pas besoin.

En gros, 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 à l'aide d'appels tels que Collections.synchronizedList - le fait que Vector combine à 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.

En ce qui concerne un équivalent Stack, je commencerai par Deque/ArrayDeque.

634
Jon Skeet

Vecteur faisait partie de 1.0 - la mise en œuvre originale présentait deux inconvénients:

1. Naming: Les vecteurs ne sont en réalité que des listes accessibles en tant que tableaux. Il aurait donc dû s'appeler ArrayList (qui est le Java 1.2 Collections de remplacement pour Vector).

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

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

De la doc API.

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

80
Justin

Outre les réponses déjà données à propos de l’utilisation de Vector, Vector propose également un ensemble de méthodes d’énumération et de récupération d’éléments différentes de l’interface List, et que les développeurs (notamment ceux qui ont appris Java avant la version 1.2) ont tendance à utiliser eux 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 au cours de l'itération, ce qui peut entraîner des problèmes. Etant donné que Vector peut être choisi pour sa synchronisation - avec l'accès au standard à partir de plusieurs threads, cela en fait un problème particulièrement pernicieux. L'utilisation de ces méthodes associe également beaucoup de code à Vector, de sorte qu'il ne sera pas facile de le remplacer par une implémentation de liste différente.

41
Yishai

Vous pouvez utiliser la méthode synchronizedCollection/List sur Java.util.Collection pour obtenir une collection thread-safe à partir d'une autre.

14
Brian Henk

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

Il hérite beaucoup plus que cela, cependant. Le fait que Java.util.Stack extends Java.util.Vector soit une erreur dans la conception orientée objet. Les puristes noteront qu’il offre aussi beaucoup de méthodes en plus des opérations traditionnellement associées à une pile (à savoir: Push, Pop, Peek, Taille). Il est également possible d'effectuer 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 non-stack de Stack.

Pour ces raisons de performance et de conceptionOOP, le JavaDoc pour Java.util.Stack recommande ArrayDeque en remplacement naturel. (Un deque est plus qu'une pile, mais au moins, il se limite à manipuler les deux extrémités, plutôt que d'offrir un accès aléatoire à tout.)

6
200_success