00:00

Difference Between ArrayList and Vector in Java

Last updated: 5 min read

ArrayList and Vector are both resizable-array implementations of List: they keep insertion order, allow duplicates and nulls, and give O(1) access by index. The key difference is that Vector synchronizes every method, while ArrayList does not. Vector is a legacy class from Java 1.0; ArrayList (Java 1.2) is its modern, faster replacement.

1. Comparison Table

ArrayList is not synchronized, Vector is synchronized
AspectArrayListVector
SynchronizationNot synchronizedAll public methods synchronized
PerformanceFaster (no locking)Slower in single-threaded code
Growth when fullAbout 50% (10 → 15)Doubles (10 → 20), or by a fixed capacityIncrement
IntroducedJava 1.2 (Collections Framework)Java 1.0 (legacy, retrofitted to List)
Legacy methodsNoneaddElement, elementAt, firstElement, capacity()…
TraversalIterator, ListIteratorAlso Enumeration
Iterator behaviourFail-fastIterator fail-fast; Enumeration not
Subclass–Stack extends Vector
Recommended?YesNo; use alternatives

2. Capacity Growth and Legacy API

GrowthAndApi.java
import java.util.*;

public class GrowthAndApi {
    public static void main(String[] args) {
        Vector<Integer> v = new Vector<>();          // default capacity 10, doubles when full
        for (int i = 0; i < 11; i++) v.add(i);
        System.out.println("Vector capacity after 11 adds: " + v.capacity());

        Vector<Integer> custom = new Vector<>(4, 3);   // capacityIncrement = 3
        for (int i = 0; i < 5; i++) custom.add(i);
        System.out.println("Vector(4, 3) capacity after 5 adds: " + custom.capacity());
        // ArrayList grows by ~50% (10 -> 15) and has no capacity() method

        // Legacy Vector API alongside the List API
        v.addElement(99);
        System.out.println("elementAt(1) = " + v.elementAt(1) + ", firstElement = " + v.firstElement()
                           + ", lastElement = " + v.lastElement());
        Enumeration<Integer> e = v.elements();
        StringBuilder sb = new StringBuilder();
        while (e.hasMoreElements()) sb.append(e.nextElement()).append(' ');
        System.out.println("Enumeration: " + sb.toString().trim());

        List<Integer> list = new ArrayList<>(v);          // both are Lists
        System.out.println("ArrayList copy size = " + list.size());
    }
}
Output
Vector capacity after 11 adds: 20
Vector(4, 3) capacity after 5 adds: 7
elementAt(1) = 1, firstElement = 0, lastElement = 99
Enumeration: 0 1 2 3 4 5 6 7 8 9 10 99
ArrayList copy size = 12

Doubling wastes more memory for large vectors; ArrayList's 50% growth is a better balance. Vector also exposes its capacity and old method names alongside the standard List methods.

3. Thread Safety

Two threads add 10,000 elements each to the same list:

ThreadSafety.java
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

public class ThreadSafety {
    static int fill(List<Integer> list) throws InterruptedException {
        Runnable task = () -> { for (int i = 0; i < 10_000; i++) list.add(i); };
        Thread a = new Thread(task), b = new Thread(task);
        a.start(); b.start(); a.join(); b.join();
        return list.size();
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println("Vector                      : " + fill(new Vector<>()));
        System.out.println("synchronizedList(ArrayList) : " + fill(Collections.synchronizedList(new ArrayList<>())));
        System.out.println("CopyOnWriteArrayList        : " + fill(new CopyOnWriteArrayList<>()));
        int unsafe;
        try { unsafe = fill(new ArrayList<>()); } catch (Exception e) { unsafe = -1; }
        System.out.println("plain ArrayList             : " + unsafe + " (often less than 20000, or an exception)");
    }
}
Output (sample run; the plain ArrayList result varies)
Vector                      : 20000
synchronizedList(ArrayList) : 20000
CopyOnWriteArrayList        : 20000
plain ArrayList             : 10061 (often less than 20000, or an exception)

An unsynchronized ArrayList loses updates or even throws ArrayIndexOutOfBoundsException when shared. But Vector's per-method locking is not enough for compound actions such as "check if absent, then add", and the locking slows down code that is not shared at all. Modern alternatives are better:

  • Collections.synchronizedList(new ArrayList<>()): same guarantees as Vector; lock on the list when iterating.
  • CopyOnWriteArrayList: excellent for lists read far more often than written (such as listener lists).
  • Concurrent queues (ConcurrentLinkedQueue, BlockingQueue) for producer-consumer work.

4. Which Should You Use?

  • Use ArrayList for normal, single-threaded or thread-confined lists.
  • Use CopyOnWriteArrayList or a synchronized wrapper when a list is shared between threads.
  • Use ArrayDeque instead of Stack.
  • Keep Vector only for legacy APIs that require it.

5. Summary

  • Both are dynamic-array lists with O(1) index access.
  • Vector is synchronized and slower; ArrayList is unsynchronized and faster.
  • Vector doubles its capacity; ArrayList grows by about 50%.
  • Vector is legacy: prefer ArrayList, or concurrent collections for shared lists.

Related Tutorials