Java ArrayList vs Vector

Panoramica

In questo tutorial, ci concentreremo sulle differenze tra le classi ArrayList e Vector. Entrambi appartengono al framework Java Collections e implementano java.util.Interfaccia elenco.

Tuttavia, queste classi presentano differenze significative nelle loro implementazioni.

Cosa c’è di diverso?

Come avvio rapido, presentiamo le differenze chiave di ArrayList e Vector. Quindi, discuteremo alcuni dei punti in modo più dettagliato:

  • sincronizzazione – La prima grande differenza tra questi due. Vector è sincronizzato e ArrayList no.
  • crescita delle dimensioni-Un’altra differenza tra i due è il modo in cui ridimensionano mentre raggiungono la loro capacità. Il Vettore raddoppia le sue dimensioni. Al contrario, ArrayList aumenta solo della metà della sua lunghezza
  • iterazione – E Vector può utilizzare Iteratore ed Enumerazione per attraversare gli elementi. D’altra parte, ArrayList può utilizzare solo Iterator.
  • prestazioni-In gran parte a causa della sincronizzazione, le operazioni vettoriali sono più lente rispetto a ArrayList
  • framework-Inoltre, ArrayList fa parte del framework delle collezioni ed è stato introdotto in JDK 1.2. Nel frattempo, Vector è presente nelle versioni precedenti di Java come classe legacy.

Vector

Poiché abbiamo già una guida estesa su ArrayList, non discuteremo le sue API e funzionalità qui. D’altra parte, presenteremo alcuni dettagli fondamentali su Vector.

In poche parole, un vettore è un array ridimensionabile. Può crescere e ridursi quando aggiungiamo o rimuoviamo gli elementi.

Possiamo creare un vettore in modo tipico:

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

Il costruttore predefinito crea un vettore vuoto con una capacità iniziale di 10.

Aggiungiamo alcuni valori:

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

E infine, scorrere i valori utilizzando l’interfaccia Iteratore:

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

Oppure, possiamo attraversare il vettore usando l’enumerazione:

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

Ora, cerchiamo di esplorare alcune delle loro caratteristiche uniche in modo più approfondito.

Concorrenza

Abbiamo già detto che ArrayList e Vector sono diversi nella loro strategia di concorrenza, ma diamo un’occhiata più da vicino. Se dovessimo immergerci nelle firme del metodo di Vector, vedremmo che ognuna ha la parola chiave sincronizzata:

public synchronized E get(int index)

In poche parole, questo significa che solo un thread può accedere a un dato vettore alla volta.

In realtà, tuttavia, queste sincronizzazioni a livello di operazione devono essere sovrapposte comunque con la nostra sincronizzazione per le operazioni composte.

Quindi, al contrario, ArrayList adotta un approccio diverso. I suoi metodi non sono sincronizzati e tale preoccupazione è separata in classi dedicate alla concorrenza.

Ad esempio, possiamo usare CopyOnWriteArrayList o Collections.synchronizedList per ottenere un effetto simile a Vector:

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

Prestazioni

Come abbiamo già discusso in precedenza, Vector è sincronizzato che causa un impatto diretto sulle prestazioni.

Per vedere la differenza di prestazioni tra le operazioni Vector e ArrayList, scriviamo un semplice test di benchmark JMH.

In passato, abbiamo esaminato la complessità temporale delle operazioni di ArrayList, quindi aggiungiamo i casi di test per Vector.

Per prima cosa, testiamo il metodo 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);}

Configureremo JMH per utilizzare tre thread e 10 iterazioni di riscaldamento.

E, riportiamo il tempo medio per operazione a livello di nanosecondi:

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

Possiamo vedere che ArrayList # get funziona circa tre volte più velocemente di Vector # get.

Ora, confrontiamo i risultati dell’operazione 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);}

E stampare i risultati:

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

Come possiamo vedere, per l’operazione contains (), il tempo di prestazione per Vector è molto più lungo di ArrayList.

Sommario

In questo articolo, abbiamo dato un’occhiata alle differenze tra le classi Vector e ArrayList in Java. Inoltre, abbiamo anche presentato le funzionalità vettoriali in maggiori dettagli.

Come al solito, il codice completo per questo articolo è disponibile su GitHub.

Inizia con Spring 5 e Spring Boot 2, attraverso il corso Learn Spring:

>> CONTROLLA IL CORSO



+