Java ArrayList vs Vector

1. Übersicht

In diesem Tutorial konzentrieren wir uns auf die Unterschiede zwischen den Klassen ArrayList und Vector . Beide gehören zum Java Collections Framework und implementieren die Schnittstelle java.util.List .

Diese Klassen weisen jedoch erhebliche Unterschiede in ihren Implementierungen auf.

2. Was ist anders?

Lassen Sie uns zunächst die wichtigsten Unterschiede zwischen ArrayList und Vector vorstellen . Dann werden wir einige der Punkte genauer besprechen:

  • Synchronisation - Der erste große Unterschied zwischen diesen beiden. Der Vektor ist synchronisiert und die ArrayList nicht.
  • Größenwachstum - Ein weiterer Unterschied zwischen den beiden ist die Art und Weise, wie sie die Größe ändern, während sie ihre Kapazität erreichen. Der Vektor verdoppelt seine Größe. Im Gegensatz dazu erhöht sich ArrayList nur um die Hälfte seiner Länge
  • Iteration - Und Vector kann Iterator und Enumeration verwenden , um die Elemente zu durchlaufen. Andererseits kann ArrayList nur Iterator verwenden .
  • Leistung - Weitgehend aufgrund Synchronisation, Vektor sind Operationen langsamer im Vergleich zu Arraylist
  • Framework - ArrayList ist auch Teil des Collections-Frameworks und wurde in JDK 1.2 eingeführt. Inzwischen ist Vector in früheren Versionen von Java als Legacy-Klasse vorhanden.

3. Vektor

Da wir bereits eine erweiterte Anleitung zu ArrayList haben, werden wir hier nicht auf die API und die Funktionen eingehen. Auf der anderen Seite werden wir einige wichtige Details zu Vector vorstellen .

Einfach ausgedrückt ist ein Vektor ein Array mit veränderbarer Größe . Es kann wachsen und schrumpfen, wenn wir die Elemente hinzufügen oder entfernen.

Wir können auf typische Weise einen Vektor erstellen:

Vector vector = new Vector();

Der Standardkonstruktor erstellt einen leeren Vektor mit einer Anfangskapazität von 10.

Fügen wir einige Werte hinzu:

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

Lassen Sie uns abschließend die Werte mithilfe der Iterator- Schnittstelle durchlaufen :

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

Oder wir können den Vektor mithilfe der Aufzählung durchlaufen :

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

Lassen Sie uns nun einige ihrer einzigartigen Funktionen genauer untersuchen.

4. Parallelität

Wir haben bereits erwähnt, dass ArrayList und Vector sich in ihrer Parallelitätsstrategie unterscheiden, aber schauen wir uns das genauer an. Wenn wir in die Methodensignaturen von Vector eintauchen würden, würden wir sehen, dass jedes das synchronisierte Schlüsselwort hat:

public synchronized E get(int index)

Einfach ausgedrückt bedeutet dies, dass jeweils nur ein Thread auf einen bestimmten Vektor zugreifen kann .

In Wirklichkeit müssen diese Synchronisierungen auf Operationsebene ohnehin mit unserer eigenen Synchronisation für zusammengesetzte Operationen überlagert werden.

Im Gegensatz dazu verfolgt ArrayList einen anderen Ansatz. Die Methoden sind nicht synchronisiert, und dieses Problem wird in Klassen unterteilt, die sich der Parallelität widmen.

Beispielsweise können wir CopyOnWriteArrayList oder Collections.synchronizedList verwenden , um einen ähnlichen Effekt wie Vector zu erzielen :

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

5. Leistung

Wie bereits oben erläutert, ist Vector synchronisiert, was sich direkt auf die Leistung auswirkt .

Um den Leistungsunterschied zwischen Vector- und ArrayList- Operationen zu erkennen, schreiben wir einen einfachen JMH-Benchmark-Test.

In der Vergangenheit haben wir uns mit der zeitlichen Komplexität der ArrayList -Operationen befasst. Fügen wir also die Testfälle für Vector hinzu.

Erstens , lassen Sie uns Test der get () Methode:

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

Wir werden JMH so konfigurieren, dass drei Threads und 10 Aufwärmiterationen verwendet werden.

Lassen Sie uns über die durchschnittliche Zeit pro Operation im Nanosekundenbereich berichten:

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

Wir können sehen, dass ArrayList # get ungefähr dreimal schneller funktioniert als Vector # get .

Vergleichen wir nun die Ergebnisse der Operation includes () :

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

Und drucken Sie die Ergebnisse aus:

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

Da wir für die sehen können , enthält () Betrieb, die Leistungszeit für Vector ist viel länger als Arraylist .

6. Zusammenfassung

In diesem Artikel haben wir uns die Unterschiede zwischen den Klassen Vector und ArrayList in Java angesehen. Darüber hinaus haben wir die Vektorfunktionen ausführlicher vorgestellt.

Wie üblich ist der vollständige Code für diesen Artikel auf GitHub verfügbar.