Java ArrayList vs Vector

Aperçu

Dans ce tutoriel, nous allons nous concentrer sur les différences entre les classes ArrayList et Vector. Ils appartiennent tous deux au framework Java Collections et implémentent java.util.Interface de liste.

Cependant, ces classes présentent des différences significatives dans leurs implémentations.

Qu’est-ce qui est différent?

Pour commencer rapidement, présentons les principales différences entre ArrayList et Vector. Ensuite, nous discuterons de certains points plus en détail:synchronisation

  • – La première différence majeure entre ces deux. Le vecteur est synchronisé et ArrayList ne l’est pas.
  • croissance de la taille – Une autre différence entre les deux est la façon dont ils se redimensionnent tout en atteignant leur capacité. Le vecteur double sa taille. En revanche, ArrayList n’augmente que de moitié de sa longueur
  • itération – Et le vecteur peut utiliser l’Itérateur et l’énumération pour parcourir les éléments. D’un autre côté, ArrayList ne peut utiliser qu’Iterator.performances
  • – En grande partie en raison de la synchronisation, les opérations vectorielles sont plus lentes par rapport au framework ArrayList
  • – En outre, ArrayList fait partie du framework Collections et a été introduit dans JDK 1.2. Pendant ce temps, Vector est présent dans les versions antérieures de Java en tant que classe héritée.

Vector

Comme nous avons déjà un guide étendu sur ArrayList, nous ne discuterons pas de son API et de ses capacités ici. D’un autre côté, nous présenterons quelques détails de base sur Vector.

En termes simples, un vecteur est un tableau redimensionnable. Il peut croître et rétrécir à mesure que nous ajoutons ou supprimons les éléments.

Nous pouvons créer un vecteur de manière typique:

Vector<String> vector = new Vector<>();

Le constructeur par défaut crée un vecteur vide d’une capacité initiale de 10.

Ajoutons quelques valeurs:

vector.add("baeldung");vector.add("Vector");vector.add("example");

Et enfin, parcourons les valeurs en utilisant l’interface de l’itérateur:

Iterator<String> iterator = vector.iterator();while (iterator.hasNext()) { String element = iterator.next(); // ...}

Ou, nous pouvons parcourir le vecteur en utilisant l’énumération:

Enumeration e = vector.elements();while(e.hasMoreElements()) { String element = e.nextElement(); // ... }

Maintenant, explorons plus en profondeur certaines de leurs caractéristiques uniques.

Concurrence

Nous avons déjà mentionné que ArrayList et Vector sont différents dans leur stratégie de concurrence, mais regardons de plus près. Si nous devions plonger dans les signatures de méthode de Vector, nous verrions que chacune a le mot-clé synchronisé:

public synchronized E get(int index)

En termes simples, cela signifie qu’un seul thread peut accéder à un vecteur donné à la fois.

Cependant, ces synchronisations au niveau des opérations doivent de toute façon être superposées à notre propre synchronisation pour les opérations composées.

Donc, en revanche, ArrayList adopte une approche différente. Ses méthodes ne sont pas synchronisées et cette préoccupation est séparée en classes consacrées à la concurrence.

Par exemple, nous pouvons utiliser CopyOnWriteArrayList ou Collections.synchronizedList pour obtenir un effet similaire à Vector:

vector.get(1); // synchronizedCollections.synchronizedList(arrayList).get(1); // also synchronized

Performance

Comme nous l’avons déjà discuté ci-dessus, le vecteur est synchronisé, ce qui a un impact direct sur les performances.

Pour voir la différence de performance entre les opérations vectorielles et ArrayList, écrivons un test de référence JMH simple.

Dans le passé, nous avons examiné la complexité temporelle des opérations de ArrayList, ajoutons donc les cas de test pour Vector.

Tout d’abord, testons la méthode get():

@Benchmarkpublic Employee testGet(ArrayListBenchmark.MyState state) { return state.employeeList.get(state.employeeIndex);}@Benchmarkpublic Employee testVectorGet(ArrayListBenchmark.MyState state) { return state.employeeVector.get(state.employeeIndex);}

Nous allons configurer JMH pour utiliser trois threads et 10 itérations d’échauffement.

Et rapportons le temps moyen par opération au niveau de la nanoseconde:

Benchmark Mode Cnt Score Error UnitsArrayListBenchmark.testGet avgt 20 9.786 ± 1.358 ns/opArrayListBenchmark.testVectorGet avgt 20 37.074 ± 3.469 ns/op

Nous pouvons voir que ArrayList #get fonctionne environ trois fois plus vite que Vector #get.

Maintenant, comparons les résultats de l’opération contains():

@Benchmarkpublic boolean testContains(ArrayListBenchmark.MyState state) { return state.employeeList.contains(state.employee);}@Benchmarkpublic boolean testContainsVector(ArrayListBenchmark.MyState state) { return state.employeeVector.contains(state.employee);}

Et imprimez les résultats:

Benchmark Mode Cnt Score Error UnitsArrayListBenchmark.testContains avgt 20 8.665 ± 1.159 ns/opArrayListBenchmark.testContainsVector avgt 20 36.513 ± 1.266 ns/op

Comme nous pouvons le voir, pour l’opération contains(), le temps de performance du vecteur est beaucoup plus long que ArrayList.

Résumé

Dans cet article, nous avons examiné les différences entre les classes Vector et ArrayList en Java. De plus, nous avons également présenté les fonctionnalités vectorielles plus en détail.

Comme d’habitude, le code complet de cet article est disponible sur GitHub.

Commencez avec Spring 5 et Spring Boot 2, à travers le cours Learn Spring:

>> DÉCOUVREZ LE COURS



+