Skip to main content

Vector in Java

Vector Deep Dive: Internal Backend Working

The Vector class is a relic of Java's past. Introduced all the way back in JDK 1.0 (before the modern Collections Framework even existed), it is a dynamic, resizable array. On the surface, its architecture is almost identical to an ArrayList.

However, it possesses one foundational difference that dictates how it behaves, why it is slow, and why modern Java developers almost never use it: Every single method in a Vector is synchronized.

[ The Hierarchy ] Iterable ↓ Collection ↓ List ↓ Vector

1. Internal Data Structure

If you look at the raw source code of java.util.Vector, the storage mechanism is straightforward. It relies on three primary fields to manage its data and growth:

public class Vector<E> { protected Object[] elementData; // The actual array protected int elementCount; // Current size (items inserted) protected int capacityIncrement; // Growth rate controller }

Unlike a modern ArrayList which uses lazy allocation (creating the array only when the first element is added), a default Vector immediately allocates an array of 10 slots in memory the moment it is instantiated.


2. The Growth Strategy: 2x Expansion

When an ArrayList fills up, it grows by 1.5x (50%). A Vector takes a much more aggressive approach to avoid frequent resizing operations. By default, when a Vector is completely full, it doubles its capacity (2x).

10
20
30
40
Resizes To
80

Customizing the Growth Rate

Vector offers a unique constructor that allows you to manually control the exact capacity increment, rather than strictly doubling.

// Initial capacity = 10, Growth increment = 5 Vector<Integer> v = new Vector<>(10, 5);

If you set a custom increment, the Vector will grow linearly ($10 \rightarrow 15 \rightarrow 20 \rightarrow 25$) instead of exponentially. If capacityIncrement is left at 0, it defaults to doubling.


3. The Synchronization Bottleneck

This is the core identity of the Vector class. To make it thread-safe, Java uses an Object Monitor Lock. Look at the method signature for adding an element:

public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; }

Because the method is marked synchronized, only one thread can execute this method at a time across the entire object instance.

  • If Thread A calls v.add(10), it locks the entire Vector.
  • If Thread B wants to call v.get(5), it is completely blocked. It must wait until Thread A finishes inserting its data and releases the lock.

This creates massive Thread Contention. Even in a single-threaded application where no other threads exist, the JVM still wastes CPU cycles acquiring and releasing the monitor lock for every single operation. This is why Vector is fundamentally slower than ArrayList.

The "Check-Then-Act" Race Condition

Many developers mistakenly believe that because a Vector is synchronized, it makes their application completely safe. This is false. Vector only protects individual methods. Compound operations are still highly vulnerable to race conditions.

if (!v.isEmpty()) { // Thread B could remove the last item right here! v.remove(0); // Thread A crashes with ArrayIndexOutOfBoundsException }

To safely execute a check-then-act operation on a Vector, you must still wrap the entire block in an external synchronized(v) block—defeating the entire purpose of using a Vector in the first place.


4. Backend Operations & Complexity

Accessing Data: get()

Because Vector is backed by an array, it utilizes contiguous memory. Fetching data is a simple mathematical address calculation: $\text{Base} + (\text{Index} \times \text{Size})$. This makes random access lightning fast at $O(1)$.

Removing Data: remove()

Removing an item from the middle of a Vector requires shifting all subsequent elements to the left to close the gap. It executes this using System.arraycopy(). Because it requires moving elements, deletion (and middle insertion) operates at $O(n)$.


5. Legacy Enumeration vs. Modern Iterator

Before the Iterator interface was introduced in JDK 1.2, Java used Enumeration to loop over collections. Vector still heavily supports this legacy feature.

Feature Enumeration (Legacy) Iterator (Modern)
Supported By Vector, Hashtable All Collection Classes
Remove Elements? No (Read-only) Yes (Using it.remove())
Fail-Fast? No. Can cause silent corruption if modified during looping. Yes. Throws ConcurrentModificationException instantly.
Method Names hasMoreElements(), nextElement() hasNext(), next()

6. Vector vs. ArrayList: The Ultimate Showdown

Feature Vector ArrayList
Thread Safe? Yes (Method-level locking) No
Performance Slower (Locking overhead) Faster
Growth Strategy Doubles (2x) by default Grows by 1.5x (50%)
Legacy Class? Yes (JDK 1.0) No (Introduced in JDK 1.2)

The Modern Verdict

In modern backend architecture, you should almost never use Vector. It is retained purely for backward compatibility with ancient enterprise systems.

  • If you are working in a single-threaded environment: Use ArrayList.
  • If you need a thread-safe dynamic array: Use Collections.synchronizedList(new ArrayList<>()).
  • If you are building a highly concurrent, read-heavy system: Use CopyOnWriteArrayList, which abandons harsh locking entirely by creating a fresh copy of the array on every write, allowing lock-free reads.

Comments

Popular posts from this blog

How I Got Selected in MNC

Virtusa Sometimes success does not come from having the best coding skills or the perfect roadmap. Sometimes it comes from simply refusing to quit. This is the honest story of how I transitioned from a confused, rejected fresher to getting selected as an Associate Engineer at Virtusa. The Beginning: Confused About My Future After completing my graduation, I stared blankly at my career options. Like many freshers, I lacked a clear direction. Should I join a Java course? Should I prepare on my own? Should I just wait for campus placement opportunities? One day, I called my friend Chetan. He suggested I join Naresh i Technologies and start learning Java seriously. Still unsure of my path, I told him I needed time to think about it. A couple of days later, my phone buzzed with a WhatsApp message offering a job opportunity. They asked me to come for the next round of the recruitment process. Excitement completely took over. I packed my bags, traveled to th...

Spring Boot Introduction

Spring Boot Introduction: Architecture, Dependencies, and Embedded Servers Modern enterprise applications demand rapid development, frictionless deployment, and absolute minimal configuration. Before Spring Boot arrived, developers utilizing the Spring Framework wasted immense amounts of time configuring XML files, managing clashing dependencies, setting up clunky application servers, and stitching various Spring modules together manually. To eliminate these bottlenecks, Pivotal introduced Spring Boot . Built entirely on top of the traditional Spring Framework, Spring Boot is an "opinionated" framework. It aggressively simplifies application development by injecting auto-configuration, packaging starter dependencies, and embedding web servers directly into your application. This allows backend developers to focus entirely on building business logic rather than wrestling with infrastructure setup. What is Spring Boot? Spring Boot is a powerful extens...

Data Types in C

C Programming: Understanding Data Types Think of your kitchen. You store a large bag of flour in a big bin, a pinch of saffron in a tiny jar, and milk in a liquid measuring jug. You do not put liquids into paper bags, and you do not use a massive bucket for a single teaspoon of sugar. C programming works the exact same way. When you create a variable, you must tell the computer exactly what kind of "container" to build in its memory. We call these containers Data Types . They dictate what kind of data the container holds, how much space it takes up, and what operations you can perform on it. 1. Primitive Data Types C offers several built-in, "primitive" data types. Think of these as the fundamental storage containers. int (Integer): You use this to store whole numbers without decimals. Real-life example: Counting the number of people in a room or tracking a player's score in a video game. char (Character): You use this ...