Java – Confronto tra ArrayList e Vector

Tra le varie collezioni contenute nel Java Collections Framework della piattaforma Standard Edition di Java, esistono le due ben note classi java.util.ArrayList e java.util.Vector. Sono due “collezioni” molto simili come concetti e funzionalità, quindi si prestano molto bene ad essere messe a confronto.
Non sono certamente il primo che si occupa di fare una analisi di questo tipo ma con questo breve articolo l’obiettivo è di esporre in maniera chiara e puntuale tutte le similitudini e le differenze più rilevanti che si possono riscontrare su queste due collezioni.

Similitudini tra ArrayList e Vector

  1. Entrambe le collezioni rappresentano una sequenza lineare di elementi indirizzabili tramite un indice numerico di tipo int che va da 0 a lunghezza-1 (dove lunghezza è il risultato del metodo size()).

  2. Entrambe le collezioni sono espandibili e ridimensionabili “dinamicamente”, come avviene in generale anche per tutte le altre collezioni.

  3. Entrambe le collezioni sono basate internamente su un singolo array che viene gestito a “capacità più espansa”, cioè per la maggior parte del tempo la capacità fisica dell’array interno è ben maggiore rispetto al numero “logico” di elementi realmente presenti. Quando la capacità fisica dell’array non è più sufficiente, la collezione crea un nuovo array più ampio, copiandoci dentro gli elementi dal “vecchio” array che viene poi alla fine rimpiazzato dal nuovo.

  4. Entrambe le collezioni permettono l’inserimento di valori null.

  5. Entrambe le collezioni a partire dal JDK 5 sono classi “generiche” nel senso che sfruttano i generics introdotti in Java 5 e quindi possono essere utilizzate parametrizzate (es. ArrayList<String> e Vector<String> ).

  6. Entrambe le collezioni implementano (direttamente o indirettamente) le interfacce:

    • Cloneable
    • Collection<E>
    • Iterable<E> (a partire dal JDK 5)
    • List<E>
    • RandomAccess
    • Serializable

  7. Entrambe le collezioni forniscono un iterator (intendendo qui in generale sia java.util.Iterator, sia java.util.ListIterator) che ha il comportamento indicato con l’espressione fail-fast, cioè la iterazione fallisce lanciando l’eccezione java.util.ConcurrentModificationException nel momento in cui l’iteratore riesce a determinare che la collezione è stata modificata strutturalmente utilizzando qualunque metodo di modifica eccetto quelli forniti specificatamente da Iterator/ListIterator.

Differenze tra ArrayList e Vector

  1. Vector esiste dal JDK 1.0 mentre ArrayList esiste dal JDK 1.2 (versione in cui è stato introdotto il Java Collections Framework). Vector è una collezione definita “legacy” ed è tuttora mantenuta nel framework principalmente per motivi di compatibilità.

  2. Vector ha un costruttore che riceve initialCapacity e capacityIncrement che invece ArrayList non possiede.

  3. Vector ha svariati metodi “legacy” che invece ArrayList non possiede:

    • void addElement(E obj)
    • int capacity()
    • void copyInto(Object[] anArray)
    • E elementAt(int index)
    • Enumeration<E> elements()
    • E firstElement()
    • void insertElementAt(E obj, int index)
    • E lastElement()
    • void removeAllElements()
    • boolean removeElement(Object obj)
    • void removeElementAt(int index)
    • void setElementAt(E obj, int index)
    • void setSize(int newSize)

  4. Vector è in grado di fornire una enumeration (java.util.Enumeration) mentre ArrayList non offre questa funzionalità. Inoltre, il Enumeration fornito da Vector non ha il comportamento fail-fast.

  5. Vector è una classe thread-safe, tutti i suoi metodi sono “sincronizzati”, cioè la invocazione di uno qualunque dei suoi metodi acquisisce il monitor (lock) intrinseco dell’oggetto Vector per garantire la “mutua esclusione” tra thread. ArrayList invece non è thread-safe e non offre alcun meccanismo di sincronizzazione.

  6. Le due collezioni differiscono nella logica impiegata per calcolare la nuova capacità da utilizzare per creare un array più “ampio”. In particolare, storicamente e fin dal principio, Vector ha sempre applicato un fattore di moltiplicazione di 2x mentre ArrayList ha sempre applicato un fattore di moltiplicazione di 1,5x rispetto alla capacità “corrente”.
    NOTA: questo è un dettaglio implementativo (non documentato ufficialmente) che risulta ben noto dalla analisi dei sorgenti del framework nel JDK di Sun/Oracle.

  7. Vector funge da classe “base” per la collezione chiamata Stack mentre ArrayList fa da classe “base” per alcune classi molto specializzate che fanno parte della API del management (package javax.management).