Vector Implementation Analysis in Java

Vector Overview

Vector is a thread-safe implementation of a dynamic array in Java, similar to ArrayList but with synchronized operations. It extands AbstractList and implements List, RandomAccess, Cloneable, and Serializable interfaces.


public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
}

Core Fields

The internal structure uses an array to store elements with several key properties:


protected Object[] elementData;    // Storage array
protected int elementCount;        // Actual element count
protected int capacityIncrement;   // Capacity growth factor
private static final long serialVersionUID = -2767605614048989439L;

Constructors

Vector provides four constructor variations:


// Constructor with initial capacity and growth factor
public Vector(int initialCapacity, int capacityIncrement) {
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
    this.elementData = new Object[initialCapacity];
    this.capacityIncrement = capacityIncrement;
}

// Default constructor with capacity 10
public Vector() {
    this(10);
}

// Collection-based initialization
public Vector(Collection<? extends E> c) {
    Object[] items = c.toArray();
    elementCount = items.length;
    if (c.getClass() == ArrayList.class) {
        elementData = items;
    } else {
        elementData = Arrays.copyOf(items, elementCount, Object[].class);
    }
}

Core Operations

Element Addition

Adding elements with automatic capacity expansion:


public synchronized void addElement(E element) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = element;
}

private void ensureCapacityHelper(int minCapacity) {
    if (minCapacity - elementData.length > 0)
        expandCapacity(minCapacity);
}

private void expandCapacity(int minCapacity) {
    int currentCapacity = elementData.length;
    int newCapacity = currentCapacity + ((capacityIncrement > 0) ? 
                         capacityIncrement : currentCapacity);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = calculateMaxCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}

Element Removal

Thread-safe element removal operations:


public synchronized boolean removeElement(Object target) {
    modCount++;
    int position = indexOf(target);
    if (position >= 0) {
        removeElementAt(position);
        return true;
    }
    return false;
}

public synchronized void removeElementAt(int index) {
    modCount++;
    if (index >= elementCount) {
        throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
    }
    int elementsToShift = elementCount - index - 1;
    if (elementsToShift > 0) {
        System.arraycopy(elementData, index + 1, elementData, index, elementsToShift);
    }
    elementCount--;
    elementData[elementCount] = null;
}

Element Access

Safe element retrieval methods:


public synchronized E get(int index) {
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);
    return elementData(index);
}

public synchronized E firstElement() {
    if (elementCount == 0) {
        throw new NoSuchElementException();
    }
    return elementData(0);
}

Capacity Management

Manual capacity control methods:


public synchronized void trimToSize() {
    modCount++;
    int currentCapacity = elementData.length;
    if (elementCount < currentCapacity) {
        elementData = Arrays.copyOf(elementData, elementCount);
    }
}

public synchronized void ensureCapacity(int minCapacity) {
    if (minCapacity > 0) {
        modCount++;
        ensureCapacityHelper(minCapacity);
    }
}

Iterators

Vector provides three iterator implementations for different use cases:


// Basic iterator
private class BasicIterator implements Iterator<E> {
    int nextIndex;
    int lastReturned = -1;
    int expectedModCount = modCount;

    public boolean hasNext() {
        return nextIndex != elementCount;
    }

    public E next() {
        synchronized (Vector.this) {
            checkModification();
            int i = nextIndex;
            if (i >= elementCount)
                throw new NoSuchElementException();
            nextIndex = i + 1;
            return elementData(lastReturned = i);
        }
    }
}

// List iterator with extended functionality
final class ListIterator extends BasicIterator implements ListIterator<E> {
    ListIterator(int startIndex) {
        super();
        nextIndex = startIndex;
    }

    public boolean hasPrevious() {
        return nextIndex != 0;
    }

    public E previous() {
        synchronized (Vector.this) {
            checkModification();
            int i = nextIndex - 1;
            if (i < 0)
                throw new NoSuchElementException();
            nextIndex = i;
            return elementData(lastReturned = i);
        }
    }
}

Lambda Operations

Modern fucntional programming support:


@Override
public synchronized void forEach(Consumer<? super E> action) {
    Objects.requireNonNull(action);
    final int expectedModCount = modCount;
    final E[] data = (E[]) this.elementData;
    final int count = this.elementCount;
    for (int i = 0; modCount == expectedModCount && i < count; i++) {
        action.accept(data[i]);
    }
    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }
}

@Override
public synchronized boolean removeIf(Predicate<? super E> filter) {
    Objects.requireNonNull(filter);
    int removeCount = 0;
    final int size = elementCount;
    final BitSet removalFlags = new BitSet(size);
    final int expectedModCount = modCount;
    
    for (int i = 0; modCount == expectedModCount && i < size; i++) {
        final E element = (E) elementData[i];
        if (filter.test(element)) {
            removalFlags.set(i);
            removeCount++;
        }
    }
    
    if (removeCount > 0) {
        final int newSize = size - removeCount;
        for (int i = 0, j = 0; i < size && j < newSize; i++, j++) {
            i = removalFlags.nextClearBit(i);
            elementData[j] = elementData[i];
        }
        for (int k = newSize; k < size; k++) {
            elementData[k] = null;
        }
        elementCount = newSize;
        modCount++;
    }
    return removeCount > 0;
}

Serialization

Custom serialization handling:


private void writeObject(java.io.ObjectOutputStream stream)
        throws java.io.IOException {
    final java.io.ObjectOutputStream.PutField fields = stream.putFields();
    final Object[] data;
    synchronized (this) {
        fields.put("capacityIncrement", capacityIncrement);
        fields.put("elementCount", elementCount);
        data = elementData.clone();
    }
    fields.put("elementData", data);
    stream.writeFields();
}

Traversal Methods

Multiple approaches for element iteration:


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

// Enhanced for-loop
for(String item : data) {
    System.out.println(item);
}

// Functional approach
data.forEach(item -> System.out.println(item));

// Index-based access
for(int i = 0; i < data.size(); i++) {
    System.out.println(data.get(i));
}

// Iterator pattern
Iterator<String> iterator = data.iterator();
while(iterator.hasNext()) {
    System.out.println(iterator.next());
}

// Enumeration interface
Enumeration<String> enumeration = data.elements();
while(enumeration.hasMoreElements()) {
    System.out.println(enumeration.nextElement());
}

Vector provides thread-safe operations at the cost of performance due to synchronized methods. The default capacity is 10 with configurable growth factors. Capacity expansion involves array copying, wich can be expensive for large collections.

Tags: java vector Collections Thread-Safe data-structures

Posted on Sun, 05 Jul 2026 16:08:53 +0000 by moreshion