Java Full Course: Mastering the Language Vector Class in Java

Vector Class in Java

(Complete Notes | Beginner to Advanced | Professional & Exam-Oriented | Masterclass)

1. What is a Vector?

The Vector class implements a growable array of objects. Like a standard array, it contains components that can be accessed using an integer index. However, unlike arrays, a Vector can grow or shrink as needed to accommodate adding and removing items.

Vectors are part of the Java Collections Framework and are found in the java.util package. Since Java 1.2, Vector has been retrofitted to implement the List interface, making it a member of the Collections Framework.

Key characteristics:

  • Dynamic sizing – Automatically grows and shrinks as elements are added or removed
  • Synchronized – All methods are thread-safe, making it suitable for multi-threaded environments
  • Legacy class – Existed since Java 1.0, later adapted to work with the Collections Framework
  • RandomAccess – Implements the RandomAccess marker interface, indicating efficient index-based access
  • Type-safe – Uses generics (since Java 5) to ensure type safety

2. Class Hierarchy and Declaration

java.lang.Object ↳ java.util.AbstractCollection<E> ↳ java.util.AbstractList<E> ↳ java.util.Vector<E> ↳ java.util.Stack<E>

Class declaration:

public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable

Where E is the type of elements stored in the vector.

Direct known subclass:

  • Stack – extends Vector to implement a last-in-first-out (LIFO) stack

3. Constructors

Vector provides four constructors with different initialization options:

ConstructorDescription
Vector()Creates an empty vector with an initial capacity of 10 and a capacity increment of 0
Vector(int initialCapacity)Creates an empty vector with the specified initial capacity; capacity increment is 0
Vector(int initialCapacity, int capacityIncrement)Creates an empty vector with the specified initial capacity and capacity increment
Vector(Collection<? extends E> c)Creates a vector containing the elements of the specified collection in the order returned by the collection's iterator

Examples:

// Default vector (capacity 10, increment 0) Vector<String> defaultVector = new Vector<>(); // Vector with initial capacity 20 Vector<Integer> sizedVector = new Vector<>(20); // Vector with initial capacity 5 and increment of 3 Vector<Double> incrementalVector = new Vector<>(5, 3); // Vector from another collection ArrayList<String> list = new ArrayList<>(); list.add("A"); list.add("B"); Vector<String> fromCollection = new Vector<>(list);

Common exceptions:

  • IllegalArgumentException – if initialCapacity is negative
  • NullPointerException – if the specified collection is null

4. Protected Fields

Vector maintains three protected fields that manage its internal storage:

FieldDescription
protected Object[] elementDataThe array buffer storing vector components; its length is the vector's capacity
protected int elementCountThe number of valid components in the vector (actual size)
protected int capacityIncrementThe amount by which capacity increases when the vector overflows; if ≤ 0, capacity doubles each time

5. Capacity Management

a) Understanding Capacity vs. Size

  • Capacity – The length of the internal array (elementData.length)
  • Size (elementCount) – The number of elements actually stored in the vector

The capacity is always at least as large as the size. When elements are added beyond the current capacity, the vector automatically expands.

b) Growth Policy

The growth behavior depends on capacityIncrement:

// If capacityIncrement is specified if (capacityIncrement > 0) { newCapacity = oldCapacity + capacityIncrement; } else { // If capacityIncrement is 0 or negative, capacity doubles newCapacity = oldCapacity * 2; }

Examples:

// Doubles each time (default behavior) Vector<Integer> v1 = new Vector<>(); // capacityIncrement = 0 // Grows by 5 each time Vector<String> v2 = new Vector<>(10, 5);

c) Capacity Management Methods

MethodDescription
int capacity()Returns the current capacity of the vector
void ensureCapacity(int minCapacity)Increases capacity if necessary to hold at least minCapacity elements
void trimToSize()Reduces capacity to match the current size (minimizes memory usage)
void setSize(int newSize)Sets the size of the vector; if larger, adds null elements; if smaller, truncates

Example:

Vector<String> v = new Vector<>(5); System.out.println("Capacity: " + v.capacity()); // 5 System.out.println("Size: " + v.size()); // 0 v.add("A"); v.add("B"); v.add("C"); v.add("D"); v.add("E"); System.out.println("Size: " + v.size()); // 5 System.out.println("Capacity: " + v.capacity()); // Still 5 // Adding a 6th element triggers growth v.add("F"); System.out.println("Capacity: " + v.capacity()); // 10 (doubled) // Trim excess capacity v.trimToSize(); System.out.println("Capacity: " + v.capacity()); // 6

6. Important Methods

a) Adding Elements

MethodDescription
boolean add(E e)Appends element to the end; returns true
void add(int index, E element)Inserts element at specified position; shifts subsequent elements right
void addElement(E obj)Legacy method; adds element to the end
boolean addAll(Collection<? extends E> c)Appends all elements from the collection
boolean addAll(int index, Collection<? extends E> c)Inserts all elements at specified position
void insertElementAt(E obj, int index)Legacy method; inserts element at index

Example:

Vector<String> v = new Vector<>(); // Add elements v.add("Apple"); // [Apple] v.add("Banana"); // [Apple, Banana] v.add(1, "Cherry"); // [Apple, Cherry, Banana] // Legacy method v.addElement("Date"); // [Apple, Cherry, Banana, Date] // Add collection ArrayList<String> fruits = new ArrayList<>(); fruits.add("Elderberry"); fruits.add("Fig"); v.addAll(fruits); // [Apple, Cherry, Banana, Date, Elderberry, Fig]

b) Accessing Elements

MethodDescription
E get(int index)Returns element at specified index
E elementAt(int index)Legacy method; returns element at index
E firstElement()Returns the first element (index 0)
E lastElement()Returns the last element (size-1)
Iterator<E> iterator()Returns an iterator over elements
Enumeration<E> elements()Returns an enumeration (legacy)

Example:

Vector<String> v = new Vector<>(Arrays.asList("A", "B", "C", "D")); System.out.println(v.get(2)); // C System.out.println(v.elementAt(2)); // C System.out.println(v.firstElement()); // A System.out.println(v.lastElement()); // D // Iteration using enhanced for for (String s : v) { System.out.print(s + " "); // A B C D } // Iteration using iterator Iterator<String> it = v.iterator(); while (it.hasNext()) { System.out.print(it.next() + " "); // A B C D } // Legacy enumeration Enumeration<String> en = v.elements(); while (en.hasMoreElements()) { System.out.print(en.nextElement()); // A B C D }

c) Removing Elements

MethodDescription
E remove(int index)Removes element at index; returns removed element
boolean remove(Object o)Removes first occurrence of specified element
boolean removeAll(Collection<?> c)Removes all elements contained in the collection
void removeAllElements()Removes all elements (legacy)
boolean removeElement(Object obj)Legacy method; removes first occurrence
void removeElementAt(int index)Legacy method; removes element at index
void clear()Removes all elements

Example:

Vector<String> v = new Vector<>(); v.add("A"); v.add("B"); v.add("C"); v.add("B"); v.add("D"); System.out.println(v); // [A, B, C, B, D] // Remove by index v.remove(2); // Removes C → [A, B, B, D] // Remove by object (first occurrence) v.remove("B"); // Removes first B → [A, B, D] // Remove all elements v.clear(); // []

d) Searching and Checking

MethodDescription
boolean contains(Object o)Returns true if vector contains the element
int indexOf(Object o)Returns index of first occurrence; -1 if not found
int indexOf(Object o, int index)Searches forward from specified index
int lastIndexOf(Object o)Returns index of last occurrence
int lastIndexOf(Object o, int index)Searches backward from specified index
boolean isEmpty()Returns true if vector has no elements
int size()Returns number of elements

Example:

Vector<String> v = new Vector<>(Arrays.asList("A", "B", "C", "B", "A")); System.out.println(v.contains("C")); // true System.out.println(v.indexOf("B")); // 1 System.out.println(v.indexOf("B", 2)); // 3 (search starting from index 2) System.out.println(v.lastIndexOf("B")); // 3 System.out.println(v.lastIndexOf("B", 2)); // 1 (search backward from index 2) System.out.println(v.isEmpty()); // false System.out.println(v.size()); // 5

e) Modifying Elements

MethodDescription
E set(int index, E element)Replaces element at index; returns old element
void setElementAt(E obj, int index)Legacy method; replaces element at index
void replaceAll(UnaryOperator<E> operator)Replaces each element with result of applying operator

Example:

Vector<Integer> v = new Vector<>(Arrays.asList(1, 2, 3, 4, 5)); v.set(2, 99); // [1, 2, 99, 4, 5] v.setElementAt(100, 3); // [1, 2, 99, 100, 5] v.replaceAll(n -> n * 2); // [2, 4, 198, 200, 10]

f) Converting and Copying

MethodDescription
Object[] toArray()Returns array containing all elements
<T> T[] toArray(T[] a)Returns array of specified runtime type
void copyInto(Object[] anArray)Copies components into specified array
Object clone()Returns a shallow copy of the vector
String toString()Returns string representation

Example:

Vector<String> v = new Vector<>(Arrays.asList("X", "Y", "Z")); // Convert to array String[] arr = v.toArray(new String[0]); System.out.println(Arrays.toString(arr)); // [X, Y, Z] // Copy into existing array String[] target = new String[3]; v.copyInto(target); System.out.println(Arrays.toString(target)); // [X, Y, Z] // Clone Vector<String> clone = (Vector<String>) v.clone(); System.out.println(clone); // [X, Y, Z]

7. Vector vs. ArrayList

This is one of the most important comparisons to understand when choosing between these two classes.

FeatureVectorArrayList
Thread SafetySynchronized (thread-safe)Not synchronized (not thread-safe)
PerformanceSlower due to synchronization overheadFaster in single-threaded environments
Growth PolicyDoubles capacity (if increment ≤ 0) or adds incrementIncreases by 50% of current capacity
Legacy StatusLegacy class (Java 1.0)Part of Collections Framework (Java 1.2)
IteratorsFail-fast (except Enumeration)Fail-fast
Recommended UseMulti-threaded environments requiring thread safetySingle-threaded environments or when external synchronization is manageable

Synchronization explanation:

  • Vector methods are synchronized, meaning each method call acquires a lock
  • This makes Vector safe for concurrent access but introduces performance overhead
  • ArrayList has no such synchronization, requiring external synchronization if used in multi-threaded contexts

Performance guidance:

  • Use ArrayList in single-threaded applications for better performance
  • Use Vector only when you specifically need built-in thread safety
  • For concurrent access with ArrayList, use Collections.synchronizedList() or CopyOnWriteArrayList

8. Iterators and Fail-Fast Behavior

Vector provides two types of iteration mechanisms with different fail-fast characteristics:

a) Fail-Fast Iterators (iterator(), listIterator())

  • These iterators throw ConcurrentModificationException if the vector is structurally modified (add/remove) after iterator creation, except through the iterator's own remove or add methods
  • This behavior helps detect bugs during development

Example:

Vector<String> v = new Vector<>(Arrays.asList("A", "B", "C")); Iterator<String> it = v.iterator(); v.add("D"); // Structural modification after iterator creation while (it.hasNext()) { it.next(); // Throws ConcurrentModificationException! }

b) Non-Fail-Fast Enumeration (elements())

  • The Enumeration returned by elements() is not fail-fast
  • If the vector is modified after enumeration creation, results are undefined

Example:

Enumeration<String> en = v.elements(); v.add("D"); // Modification after enumeration creation while (en.hasMoreElements()) { System.out.println(en.nextElement()); // Behavior is undefined }

9. Complete Working Example

import java.util.*; public class VectorDemo { public static void main(String[] args) { // 1. Creating vectors with different constructors System.out.println("=== CREATING VECTORS ==="); Vector<String> v1 = new Vector<>(); // Capacity 10 Vector<Integer> v2 = new Vector<>(5); // Capacity 5 Vector<Double> v3 = new Vector<>(3, 2); // Capacity 3, increment 2 // 2. Adding elements System.out.println(" === ADDING ELEMENTS ==="); v1.add("Apple"); v1.add("Banana"); v1.add(1, "Cherry"); v1.addElement("Date"); System.out.println("Vector: " + v1); System.out.println("Size: " + v1.size()); System.out.println("Capacity: " + v1.capacity()); // 3. Adding multiple elements ArrayList<String> more = new ArrayList<>(); more.add("Elderberry"); more.add("Fig"); v1.addAll(more); System.out.println("After addAll: " + v1); // 4. Accessing elements System.out.println(" === ACCESSING ELEMENTS ==="); System.out.println("Element at index 2: " + v1.get(2)); System.out.println("First element: " + v1.firstElement()); System.out.println("Last element: " + v1.lastElement()); // 5. Searching System.out.println(" === SEARCHING ==="); System.out.println("Contains 'Banana'? " + v1.contains("Banana")); System.out.println("Index of 'Cherry': " + v1.indexOf("Cherry")); System.out.println("Last index of 'Apple': " + v1.lastIndexOf("Apple")); // 6. Iterating System.out.println(" === ITERATION ==="); System.out.print("Enhanced for: "); for (String s : v1) { System.out.print(s + " "); } System.out.print(" Iterator: "); Iterator<String> it = v1.iterator(); while (it.hasNext()) { System.out.print(it.next() + " "); } System.out.print(" Enumeration: "); Enumeration<String> en = v1.elements(); while (en.hasMoreElements()) { System.out.print(en.nextElement() + " "); } // 7. Modifying elements System.out.println(" === MODIFYING ==="); v1.set(2, "Cranberry"); System.out.println("After set: " + v1); v1.replaceAll(String::toUpperCase); System.out.println("After toUpperCase: " + v1); // 8. Removing elements System.out.println(" === REMOVING ==="); v1.remove("CHERRY"); System.out.println("After remove('CHERRY'): " + v1); v1.remove(2); System.out.println("After remove(2): " + v1); // 9. Capacity management System.out.println(" === CAPACITY MANAGEMENT ==="); v2.addAll(Arrays.asList(10, 20, 30, 40, 50)); System.out.println("v2: " + v2); System.out.println("v2 size: " + v2.size()); System.out.println("v2 capacity: " + v2.capacity()); v2.add(60); // Triggers growth System.out.println("After adding 6th element"); System.out.println("v2 capacity: " + v2.capacity()); // Doubles to 10 v2.trimToSize(); System.out.println("After trimToSize capacity: " + v2.capacity()); // 6 // 10. Vector with custom objects System.out.println(" === CUSTOM OBJECTS ==="); Vector<Student> students = new Vector<>(); students.add(new Student(101, "Alice")); students.add(new Student(102, "Bob")); students.add(new Student(103, "Charlie")); for (Student s : students) { System.out.println(s); } // 11. Converting to array System.out.println(" === CONVERTING ==="); String[] array = v1.toArray(new String[0]); System.out.println("Array: " + Arrays.toString(array)); // 12. Clearing v1.clear(); System.out.println("After clear, size: " + v1.size()); } static class Student { int id; String name; Student(int id, String name) { this.id = id; this.name = name; } @Override public String toString() { return id + ": " + name; } } }

10. When to Use Vector

Use Vector when:

  • You need thread-safe collection operations without external synchronization
  • You are working with legacy code that expects Vector
  • You need to control growth increment precisely (via capacityIncrement)
  • You are building a Stack (Vector is the parent class of Stack)

Avoid Vector and prefer ArrayList when:

  • You are working in a single-threaded environment
  • Performance is critical and synchronization overhead is undesirable
  • You want to manually control synchronization using Collections.synchronizedList()
  • You need better memory efficiency (Vector's synchronization adds overhead)

Alternative for concurrent scenarios:

  • CopyOnWriteArrayList – Provides thread safety with better performance for read-heavy workloads

11. Common Pitfalls and Best Practices

PitfallExplanation / Solution
Using Vector in single-threaded codeUnnecessary synchronization reduces performance; use ArrayList instead
Assuming Enumeration is fail-safeelements() enumeration is not fail-fast; modification during enumeration leads to undefined behavior
Not setting initial capacityVectors grow automatically, but growth requires array copying; set capacity appropriately for large datasets
Using Vector when only iteration is neededConsider ArrayList for read-heavy operations
Concurrent modification without proper synchronizationEven with Vector's synchronization, iterators are fail-fast; don't modify while iterating
Confusing size() with capacity()size() = number of elements; capacity() = internal array length

Best Practices:

  1. Initialize with appropriate capacity – Avoid repeated resizing for large collections
  2. Use trimToSize() after bulk additions – Reduce memory footprint when growth is complete
  3. Prefer ArrayList for new development – Use Vector only when thread safety is required
  4. Use enhanced for loop – More readable than Enumeration
  5. Consider Collections.synchronizedList() – Alternative for thread-safe ArrayList

12. Key Points to Remember

  • Vector is a synchronized, growable array implementation of the List interface
  • It is thread-safe – all methods are synchronized
  • Default initial capacity is 10, default growth is doubling
  • Legacy class that was retrofitted for the Collections Framework (Java 1.2)
  • Provides both modern (List interface) and legacy (addElement, elements()) methods
  • Fail-fast iterators throw ConcurrentModificationException on concurrent modification
  • Enumeration returned by elements() is not fail-fast
  • Use ArrayList for single-threaded applications; use Vector when thread safety is required
  • Parent class of Stack – use Stack for LIFO operations

Hi! Need help with studies? 👋
AI