Skip to content
Java collections 5 min read

Vector

Vector is Java’s original resizable array — it predates the Collections Framework and has been part of Java since version 1.0. Today it is considered a legacy class, but it is still used in codebases that need a thread-safe list without reaching for external concurrency utilities.

What is Vector?

Vector<E> lives in java.util and implements the List interface, so it behaves like any other list. The defining trait that separates it from ArrayList is that every public method is synchronized, meaning only one thread can read or modify the Vector at a time.

import java.util.Vector;

public class VectorBasics {
    public static void main(String[] args) {
        Vector<String> cities = new Vector<>();
        cities.add("Delhi");
        cities.add("Mumbai");
        cities.add("Bangalore");
        System.out.println(cities);
        System.out.println("Size: " + cities.size());
    }
}

Output:

[Delhi, Mumbai, Bangalore]
Size: 3

Creating a Vector

Vector provides four constructors, giving you control over initial capacity and the increment step.

import java.util.Vector;

public class VectorConstructors {
    public static void main(String[] args) {
        // Default capacity = 10
        Vector<Integer> v1 = new Vector<>();

        // Initial capacity of 20
        Vector<Integer> v2 = new Vector<>(20);

        // Initial capacity 20, grows by 5 each time capacity is exhausted
        Vector<Integer> v3 = new Vector<>(20, 5);

        // Copy constructor
        Vector<Integer> v4 = new Vector<>(v2);

        System.out.println("v1 capacity: " + v1.capacity()); // 10
        System.out.println("v3 capacity: " + v3.capacity()); // 20
    }
}

Output:

v1 capacity: 10
v3 capacity: 20

Note: capacity() returns the current internal array size, which can be larger than size() (the number of actual elements stored).

Common Methods

Vector inherits all List methods and adds a few legacy ones carried over from its pre-Collections days.

import java.util.Vector;

public class VectorMethods {
    public static void main(String[] args) {
        Vector<String> v = new Vector<>();

        // Adding elements
        v.add("Apple");
        v.addElement("Banana");   // legacy alias for add()
        v.add(1, "Mango");        // insert at index 1

        System.out.println("List: " + v);

        // Accessing elements
        System.out.println("First: " + v.get(0));
        System.out.println("elementAt(2): " + v.elementAt(2)); // legacy

        // Updating
        v.set(0, "Apricot");
        System.out.println("After set: " + v);

        // Removing
        v.remove("Mango");
        v.removeElementAt(1);     // legacy alias
        System.out.println("After remove: " + v);

        // Searching
        System.out.println("Contains Apricot: " + v.contains("Apricot"));
        System.out.println("Index of Apricot: " + v.indexOf("Apricot"));

        // Size and capacity
        System.out.println("Size: " + v.size());
        System.out.println("Empty: " + v.isEmpty());
    }
}

Output:

List: [Apricot, Mango, Banana]
First: Apple
elementAt(2): Banana
After set: [Apricot, Mango, Banana]
After remove: [Apricot]
Contains Apricot: true
Index of Apricot: 0
Size: 1
Empty: false

Iterating a Vector

You can iterate using the modern for-each loop, an Iterator, or the classic Enumeration (legacy).

import java.util.Enumeration;
import java.util.Vector;

public class VectorIteration {
    public static void main(String[] args) {
        Vector<Integer> numbers = new Vector<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);

        // Modern for-each
        System.out.print("for-each: ");
        for (int n : numbers) {
            System.out.print(n + " ");
        }

        // Legacy Enumeration
        System.out.print("\nEnumeration: ");
        Enumeration<Integer> e = numbers.elements();
        while (e.hasMoreElements()) {
            System.out.print(e.nextElement() + " ");
        }
        System.out.println();
    }
}

Output:

for-each: 10 20 30 
Enumeration: 10 20 30 

Thread Safety in Action

Because all methods are synchronized, Vector is safe to share between threads without additional locking.

import java.util.Vector;

public class VectorThreadSafety {
    public static void main(String[] args) throws InterruptedException {
        Vector<Integer> shared = new Vector<>();

        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                shared.add(i);
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        t1.start();
        t2.start();
        t1.join();
        t2.join();

        // Always exactly 2000 — no data race possible
        System.out.println("Final size: " + shared.size());
    }
}

Output:

Final size: 2000

Warning: Synchronization at the method level does not make compound operations atomic. For example, a check-then-act sequence like if (!v.contains(x)) v.add(x) is still not thread-safe without an external lock, because another thread can sneak in between the two calls.

Under the Hood

Memory and Growth

Internally, Vector stores elements in an Object[] array. When you add an element and the array is full, Vector doubles the internal array by default. You can override this with the capacityIncrement constructor parameter — if you set it to, say, 5, the array grows by exactly 5 slots each time instead of doubling.

BehaviorArrayListVector
Default initial capacity1010
Growth strategy50% increase (oldCapacity + oldCapacity >> 1)Double (or capacityIncrement if set)
SynchronizationNoneEvery public method

How Synchronization Works

Each synchronized method in Vector acquires the intrinsic lock on the Vector object before executing. This is identical to marking the method with the synchronized keyword yourself. While safe, it means:

  • One thread at a time can access the vector, even for reads.
  • Under high contention, threads queue up waiting for the lock, causing measurable performance overhead compared to unsynchronized ArrayList.

For scenarios where you need concurrent access but want better throughput, prefer java.util.concurrent.CopyOnWriteArrayList (from the concurrent collections) or wrap an ArrayList with Collections.synchronizedList().

Vector vs ArrayList

FeatureVectorArrayList
Packagejava.utiljava.util
Thread-safeYes (method-level sync)No
Growth strategyDoubles (default)~50% increase
Legacy API (elementAt, addElement)YesNo
Enumeration supportYesNo
Performance (single-threaded)Slower (lock overhead)Faster
Introduced inJava 1.0Java 1.2

See the dedicated ArrayList vs Vector page for a deeper comparison.

Stack — A Subclass of Vector

java.util.Stack extends Vector and adds classic push/pop/peek semantics. Because it inherits all of Vector’s methods, you can accidentally call add(index, element) on a Stack, which breaks the LIFO contract. For a proper stack, prefer Deque/ArrayDeque.

import java.util.Stack;

public class StackDemo {
    public static void main(String[] args) {
        Stack<String> stack = new Stack<>();
        stack.push("first");
        stack.push("second");
        stack.push("third");

        System.out.println("Peek: " + stack.peek()); // third
        System.out.println("Pop:  " + stack.pop());  // third
        System.out.println("Size: " + stack.size()); // 2
    }
}

Output:

Peek: third
Pop:  third
Size: 2

When Should You Use Vector?

Be intentional about reaching for Vector. Here is a quick decision guide:

  • Legacy codebase that already uses Vector — keep it; changing it may introduce risk.
  • You need a thread-safe list and simplicity mattersVector or Collections.synchronizedList(new ArrayList<>()) are fine for low-contention situations.
  • High-concurrency read-heavy workload — use CopyOnWriteArrayList from concurrent collections.
  • Single-threaded code — always prefer ArrayList; there is zero reason to pay the synchronization cost.

Tip: The Java documentation itself describes Vector as a legacy class and recommends using ArrayList for non-concurrent use, and CopyOnWriteArrayList or Collections.synchronizedList() for concurrent use.

  • ArrayList — the modern, unsynchronized alternative to Vector for most use cases
  • ArrayList vs Vector — a detailed side-by-side comparison of both classes
  • Stackjava.util.Stack, which extends Vector with LIFO push/pop operations
  • Concurrent Collections — modern thread-safe alternatives like CopyOnWriteArrayList and ConcurrentHashMap
  • List Interface — the common interface that Vector, ArrayList, and LinkedList all implement
  • Synchronization — how Java’s synchronized keyword and intrinsic locks work under the hood
Last updated June 13, 2026
Was this helpful?