Java Vector Basics: How Vectors Work In Java With Practical Examples
By Rohan Vats
Updated on Jun 13, 2025 | 21 min read | 7.97K+ views
Share:
For working professionals
For fresh graduates
More
By Rohan Vats
Updated on Jun 13, 2025 | 21 min read | 7.97K+ views
Share:
Table of Contents
Latest update: The Java Vector class still provides thread safety, but is slower than ArrayList in many applications. Java also introduced a new Vector API in JDK 16 that improves data processing using modern hardware. Knowing these facts can help you write more effective Java code. |
Learning Vectors in Java is crucial when building applications that require dynamic data handling with built-in thread safety. Unlike other collections available, Vector provides a synchronized, resizable array structure designed to support concurrent access without compromising data integrity.
Understanding how Vector handles synchronization, its locking mechanism, and comparing its performance to alternatives like ArrayList can significantly optimize application efficiency, particularly in concurrent environments.
This blog will explore how you can learn Java Vector for optimal performance in practical use cases.
The Vector class in Java provides a thread-safe, dynamically resizable array for storing objects, similar to JavaScript arrays. It features built-in synchronization for thread safety, automatic resizing to handle changing data sizes, and compatibility with older Java code.
Understanding these features helps you decide when to use Vector and how it differs from other collection classes like ArrayList. This knowledge lays the foundation for confidently working with Vector in your Java programs.
With a clear understanding of the Vectors in Java class and its features, you're ready to dive into how to declare and initialise a Vector in Java.
Looking to excel in the Java vector class? The following courses from upGrad can help you build the essential skills required in today's software development field.
To declare a Vector in Java, you can use the following syntax, which is efficient for dynamic data storage.
Declaring Vectors in Java requires specifying their type parameter to ensure type safety and calling the appropriate constructor to control their initial capacity and growth behavior. Understanding these details helps you optimize memory usage and performance.
In the following section, you will learn precise syntax options for Vector declaration and how each choice impacts your program.
Syntax for Declaration of Vector in Java
The declaration syntax lets you control both the initial memory allocation and how the Vector expands as elements are added:
Vector<Type> vectorName = new Vector<>(initialCapacity, capacityIncrement);
Properly tuning these parameters is critical for applications dealing with large or dynamically changing datasets, where memory management and response times are paramount.
Important Points Regarding the Increment of Vector Capacity:
Common Errors in the Declaration of Vectors
With a solid grasp of what the Vector class offers, let's now explore how you create and configure Vector instances using its constructors and their syntax.
Java Vector constructors let you create instances optimized for different scenarios. Choosing the right one depends on factors like initial capacity and growth strategy. For instance, if you're building a telemetry buffer for a monitoring application, you might use a fixed-capacity Vector to avoid frequent resizing.
Understanding these constructor options can help you manage memory and performance more effectively. In this section, you'll explore the available constructors and when to use each for best results.
Constructor overloading in Java Vector allows you to create Vector objects using different sets of parameters, providing flexibility in how you initialize capacity and content. Understanding these overloaded constructors helps you choose the most efficient way to create Vectors for your specific needs.
Next, you'll see clear examples that simplify how each constructor works and when to use them.
Vector()
This default constructor creates a Vector with an initial capacity of 10. While convenient for general use, it assumes a moderate expected size and uses the doubling strategy for capacity growth.
This means that when the Vector exceeds its capacity, it will double the size of its internal array, which can cause sudden large memory allocations if the Vector grows rapidly.
Vector<E> defaultVector = new Vector<E>();
This constructor is ideal if you have no prior knowledge of the data size, but should be used cautiously in memory-sensitive environments.
Vector(int initialCapacity)
By specifying the initial capacity, you allocate memory upfront, reducing the need for costly resizing operations as elements are added. This constructor helps optimize performance when you have a good estimate of the expected number of elements.
Vector<E> fixedSizeVector = new Vector<E>(initialCapacity);
Setting an accurate initial capacity improves runtime efficiency by minimizing array copies and memory reallocations.
Vector(int initialCapacity, int capacityIncrement)
This constructor extends control further by letting you set both the initial capacity and the amount by which the Vector expands once full.
Instead of doubling, the Vector grows by the fixed capacity Increment. This is particularly useful when you want predictable, incremental growth to avoid sudden spikes in memory consumption.
Vector<E> incrementalVector = new Vector<E>(initialCapacity, capacityIncrement);
Fine-tuning capacity increment allows you to balance frequent small resizes (which are costly) and large memory jumps (which may waste resources).
Vector(Collection<? extends E> c)
This constructor initializes a Vector with elements copied from an existing collection, preserving their order. The initial capacity is set to the size of the collection plus 10, which accommodates the current elements plus some room for growth.
Vector<E> copyConstructorVector = new Vector<E>(collection);
Useful when converting other collection types to Vector, ensuring efficient initialization by sizing capacity close to actual content.
Internal Mechanics Behind These Constructors:
Exceptions to Consider
Let's now compare how each constructor affects capacity in practice using a side-by-side example.
In-Depth Example: Practical Usage of Constructors:
import java.util.Vector;
public class Main {
public static void main(String[] args) {
// Default constructor: capacity 10, doubling growth
Vector<Integer> defaultVector = new Vector<>();
// Fixed initial capacity of 100, default doubling growth
Vector<Integer> fixedSizeVector = new Vector<>(100);
fixedSizeVector.add(10);
fixedSizeVector.add(20);
fixedSizeVector.add(30);
// Initial capacity 30, capacity increment 20
Vector<Integer> incrementalVector = new Vector<>(30, 20);
// Initialized from another collection (fixedSizeVector)
Vector<Integer> copyConstructorVector = new Vector<>(fixedSizeVector);
System.out.println("defaultVector capacity: " + defaultVector.capacity());
System.out.println("fixedSizeVector capacity: " + fixedSizeVector.capacity());
System.out.println("incrementalVector capacity: " + incrementalVector.capacity());
System.out.println("copyConstructorVector capacity: " + copyConstructorVector.capacity());
}
}
Expected Output:
defaultVector capacity: 10
fixedSizeVector capacity: 100
Incremental vector capacity: 30
copyConstructorVector capacity: 100
Explanation: This code demonstrates different ways to create Java Vector objects using various constructors. It shows how initial capacity and growth settings affect how much space each Vector can hold before needing to resize.
Why These Details Matter
Also Read: Understanding Constructor Chaining in Java with Examples & Implementation
By learning these constructors and their implications on memory and performance, you can write Java applications that are both efficient and scalable, handling dynamic data gracefully without unnecessary overhead.
Working with dynamic data in Java requires precise methods to handle elements without errors or slowdowns. This section addresses these challenges by explaining the essential Vector methods you need to add, access, update, and remove elements effectively. Understanding these methods will help you write clear, efficient code and maintain control over your data structures.
Knowing how to use key Java Vector methods can help you manage data efficiently and write cleaner, more reliable code.
For example, you might use add() to collect logs from multiple threads or trimToSize() to free memory in a buffer after processing.
Here's a breakdown of essential methods to keep in mind:
1. Adding Elements
Vectors in Java provide multiple methods for adding elements, including insertion at specific indices, appending at the end, and adding elements from other collections. These methods provide flexibility for managing data in dynamic environments.
Here’s a table summarizing the available methods to add elements to a Vector:
Method |
Description |
add(E e) | Appends the specified element to the end of the Vector. |
add(int index, E element) | Inserts the specified element at the given position. |
addAll(Collection<? extends E> c) | Adds all elements from the specified collection to the end of the Vector. |
addAll(int index, Collection<? extends E> c) | Inserts all elements from the collection starting at the specified index. |
addElement(E obj) | Adds the specified element to the end, increasing the size by one. |
insertElementAt(E obj, int index) | Inserts the specified element at the given index. |
set(int index, E element) | Replaces the element at the specified index with the given element. |
setElementAt(E obj, int index) | Sets the element at the specified index. |
setSize(int newSize) | Sets the size of the Vector. |
Efficient data retrieval and modification are essential for managing Vector contents, and the available methods offer precise control over element access and replacement.
2. Accessing Elements
The Vector class provides several methods to access elements, including basic element retrieval and replacing specific elements by index. It enables efficient manipulation of elements in multithreaded applications.
The following table lists the key methods for accessing elements in a Vector:
Method |
Description |
add(E e) | Appends the specified element to the end of the Vector. |
add(int index, E element) | Inserts the specified element at the given position. |
addAll(Collection<? extends E> c) | Adds all elements from the specified collection to the end of the Vector. |
addAll(int index, Collection<? extends E> c) | Inserts all elements from the collection starting at the specified index. |
addElement(E obj) | Adds the specified element to the end, increasing the size by one. |
insertElementAt(E obj, int index) | Inserts the specified element at the given index. |
set(int index, E element) | Replaces the element at the specified index with the given element. |
setElementAt(E obj, int index) | Sets the element at the specified index. |
setSize(int newSize) | Sets the size of the Vector. |
When processing data in a Vector, selecting the proper iteration method ensures efficient access and manipulation, improving performance in multithreaded environments.
3. Iteration
Vector supports various iteration methods such as using an iterator, list iterator, and enumeration, allowing developers to traverse elements in different sequences and styles. These methods are essential for processing and modifying data.
Below is a table outlining the different iteration methods provided by the Vector class:
Method |
Description |
iterator() | Returns an iterator over the elements in proper sequence. |
listIterator() | Returns a list iterator over the elements in proper sequence. |
listIterator(int index) | Returns a list iterator starting at the specified position. |
elements() | Returns an enumeration of the Vector’s elements. |
forEach(Consumer<? super E> action) | Performs the given action for each element. |
spliterator() | Creates a fail-fast Spliterator over the elements. |
subList(int fromIndex, int toIndex) | Returns a view of the Vector between fromIndex (inclusive) and toIndex (exclusive). |
Managing Vector’s internal capacity is vital for optimizing memory usage, and adjusting it allows for smoother scaling and better performance under load.
4. Capacity Management
The Vector class automatically manages its storage capacity. Methods like ensureCapacity and trimToSize allow for manual adjustments to optimize memory usage as needed.
Here is a table detailing the methods related to capacity management in Vectors:
Method |
Description |
capacity() | Returns the current storage capacity of the Vector. |
ensureCapacity(int minCapacity) | Increases capacity to ensure it can hold at least the specified number of elements. |
trimToSize() | Trims the Vector’s capacity to match its current size, freeing unused memory. |
Efficiently removing elements from a Vector ensures optimal data integrity and performance; various methods provide flexibility for specific use cases and conditions.
5. Removal
The removal methods in Vector offer flexibility for deleting elements either by index or by value, and even allow bulk removals or condition-based deletions. This is crucial for maintaining data integrity.
The following table provides an overview of the methods used to remove elements from a Vector:
Method |
Description |
remove(int index) | Removes the element at the specified position. |
remove(Object o) | Removes the first occurrence of the specified element. |
removeElement(Object obj) | Removes the first occurrence of the specified element. |
removeElementAt(int index) | Removes the element at the specified index. |
removeAll(Collection<?> c) | Removes all elements present in the specified collection. |
removeAllElements() | Removes all elements and resets the Vector size to zero. |
clear() | Removes all elements from the Vector without changing capacity. |
removeIf(Predicate<? super E> filter) | Removes all elements matching the given condition. |
removeRange(int fromIndex, int toIndex) | Removes all elements between fromIndex (inclusive) and toIndex (exclusive). |
Vector’s utility and conversion methods streamline data transformation, allowing for seamless integration with other collections and simplifying complex data manipulation tasks.
6. Utility & Conversion
Method |
Description |
clone() | Creates a shallow copy of the Vector. |
copyInto(Object[] anArray) | Copies the elements of the Vector into the specified array. |
toArray() | Returns an array containing all elements in proper order. |
toArray(T[] a) | Returns an array containing all elements; runtime type matches the specified array. |
replaceAll(UnaryOperator<E> operator) | Replaces each element by applying the given operator. |
retainAll(Collection<?> c) | Retains only elements contained in the specified collection. |
sort(Comparator<? super E> c) | Sorts the Vector according to the order induced by the Comparator. |
isEmpty() | Returns true if the Vector contains no elements. |
size() | Returns the number of elements currently in the Vector. |
Also Read: Top 32 Exception Handling Interview Questions and Answers in 2025 [For Freshers & Experienced]
While modern development avoids these, many legacy codebases still use them, so it's important to recognize deprecated methods and know when to migrate to newer alternatives.
Using outdated methods in your Java Vector code can cause problems with maintenance and compatibility. To keep your code clean and reliable, you need to know which methods are no longer supported and what to use instead.
This section highlights the top 11 deprecated Vector methods and explains safer, recommended ways to perform the same tasks.
Deprecated Method |
Reason for Deprecation |
Recommended Alternative |
addElement(E obj) | Redundant; lacks generics support and duplicates add(E e). | Use add(E e) |
capacity() | Exposes internal capacity; not reliable for logic based on size. | Use size() |
copyInto(Object[] anArray) | Requires pre-allocated Object array; unsafe and inflexible. | Use toArray() or toArray(T[] a) |
elementAt(int index) | Legacy method predating Collections Framework; duplicates get(). | Use get(int index) |
elements() | Returns legacy Enumeration; outdated iteration approach. | Use iterator() or Java Streams |
firstElement() | Redundant; duplicates get(0). | Use get(0) |
lastElement() | Redundant; duplicates get(size() - 1). | Use get(size() - 1) |
insertElementAt(E obj, int index) | Duplicates add(int index, E element). | Use add(int index, E element) |
removeElement(Object obj) | Lacks generics support; duplicates remove(Object o). | Use remove(Object o) |
removeElementAt(int index) | Duplicates remove(int index). | Use remove(int index) |
removeAllElements() | Equivalent to clear(), but a legacy method. | Use clear() |
setElementAt(E obj, int index) | Duplicates set(int index, E element). | Use set(int index, E element) |
This table highlights the most commonly deprecated methods in Java's Vector class, explaining why they are no longer recommended and what modern alternatives you should use for cleaner, safer, and more maintainable code.
Understanding the performance implications of using Java's Vector class is crucial for writing efficient applications, similar to considerations in Node.js and React. While Vectors offer built-in synchronization, this feature introduces overhead that can impact your program's speed, especially in single-threaded scenarios.
Comparing Vector with other similar classes like ArrayList helps clarify when Vector is appropriate and when it might cause bottlenecks, as seen in JavaScript environments. Beyond performance, differences in synchronization, fail-fast behavior, and how iterators handle concurrent modifications also play a key role in choosing the right class.
Synchronization Overhead
Vector methods are synchronized, meaning each operation locks the entire Vector to prevent concurrent modification issues in multi-threaded environments. While this ensures thread safety, it also causes slower performance compared to non-synchronized alternatives like ArrayList, especially when synchronization is unnecessary.
Comparison with ArrayList
Resizing Behavior
Impact on Multi-threaded Performance
When Vector May Cause Bottlenecks
Recommended Alternatives for High Performance
These limitations make Vector a suboptimal choice for most modern, concurrent Java applications.
The following simple benchmark compares how fast Vector and ArrayList perform add operations in a single-threaded context.
Note: This test does not involve concurrency—it's focused solely on single-threaded performance and does not reflect multithreaded behavior or synchronization overhead.
Code Example:
Vector<Integer> vector = new Vector<>();
ArrayList<Integer> arrayList = new ArrayList<>();
// Single-threaded add operations
long startVector = System.nanoTime();
for (int i = 0; i < 100000; i++) {
vector.add(i);
}
long durationVector = System.nanoTime() - startVector;
long startArrayList = System.nanoTime();
for (int i = 0; i < 100000; i++) {
arrayList.add(i);
}
long durationArrayList = System.nanoTime() - startArrayList;
System.out.println("Vector time (ns): " + durationVector);
System.out.println("ArrayList time (ns): " + durationArrayList);
Expected Output (sample):
Vector time (ns): 15000000
ArrayList time (ns): 7000000
Explanation:
This code measures the time taken to add 100,000 integers to both a Vector and an ArrayList in a single-threaded context. The output typically shows that ArrayList performs faster because it lacks the synchronization overhead present in Vector.
Also Read: Legacy classes in Java: What are they & Why Do They Matter?
Now that you're familiar with the Vector class's core methods, let's examine where they truly shine in real-world Java applications.
Choosing the right collection depends on how your program handles data and concurrency. This section explains four practical situations where Java Vector is useful, such as working with threads or maintaining compatibility with older code. Each use case includes a clear explanation to help you decide when Vector is the right choice.
A vector is a synchronized list in Java. This means all its methods are thread-safe by default, and no extra work is needed to keep data safe when accessed by multiple threads.
Why it's useful in concurrent environments:
Caution:
While Java Vector ensures thread safety, its coarse-grained locking can create performance bottlenecks in high-concurrency scenarios. For better scalability, consider alternatives like ConcurrentLinkedQueue that offer more efficient locking mechanisms and higher throughput.
When to use:
Code Example:
Vector<String> sessions = new Vector<>();
Runnable task = () -> {
for (int i = 0; i < 3; i++) {
sessions.add(Thread.currentThread().getName() + " - Session " + i);
}
};
Thread t1 = new Thread(task, "Thread-1");
Thread t2 = new Thread(task, "Thread-2");
t1.start();
t2.start();
Expected Output (Sample):
[Thread-1 - Session 0, Thread-1 - Session 1, Thread-1 - Session 2,
Thread-2 - Session 0, Thread-2 - Session 1, Thread-2 - Session 2]
Explanation:
Vector was widely used in Java before the ArrayList and the Collections Framework became standard. Many large, stable applications still use it.
Why it matters for legacy systems:
When to use:
Code Example:
public class OrderSystem {
private Vector<String> pendingOrders = new Vector<>();
public void addOrder(String orderId) {
pendingOrders.add(orderId);
}
public String getLastOrder() {
return pendingOrders.lastElement();
}
public void clearOrders() {
pendingOrders.removeAllElements();
}
public static void main(String[] args) {
OrderSystem system = new OrderSystem();
system.addOrder("ORD001");
system.addOrder("ORD002");
System.out.println(system.getLastOrder());
system.clearOrders();
System.out.println(system.pendingOrders.size());
}
}
Expected Output:
ORD002
0
Explanation:
Vector provides automatic synchronization, which makes it a quick solution when you just need a safe list and don't want to use wrappers or concurrency utilities.
Why it's a time-saver:
When to use:
Code Example:
List<String> events = new Vector<>();
events.add("Login Successful");
events.add("File Downloaded");
System.out.println(events);
Expected Output:
[Login Successful, File Downloaded]
Explanation:
Vector uses an internal array that automatically grows or shrinks based on the number of elements. It is ideal for dynamic data scenarios, especially when thread safety is required too.
Why it's helpful for changing data:
When to use:
Code Example:
Vector<String> notifications = new Vector<>();
notifications.add("New comment on your post");
notifications.add("Friend request received");
notifications.remove("New comment on your post");
System. out.println("Current alerts: " + notifications);
Expected Output:
Current alerts: [Friend request received]
Explanation:
When to Use Java Vector?
Use Vector when:
Avoid Vector when:
To help you quickly decide when to use Java Vector, here's a concise summary of the key use cases.
Use Cases | Why it’s Useful | When to Use |
Multithreaded Environments | Ensures thread safety with automatic synchronization for safe multi-threaded data access. | Logging, session tracking, real-time monitoring tools, or notification systems accessed by multiple threads, especially in web apps like those built with Next.js or Vue.js. |
Legacy Code Maintenance | Maintains existing thread-safe logic in large, stable legacy systems without breaking core functionality. | Maintaining large enterprise systems like ERP, banking, or telecom applications, where refactoring risks breaking core logic, as seen in systems developed with Scala. |
Quick, Drop-In Thread Safety | Provides automatic synchronization, saving time and complexity in simple, small-scale applications. | Simple scripts, logging frameworks, and background jobs with shared state requiring thread safety. |
Dynamic Arrays with Frequent Additions/Removals | Handles dynamic data resizing safely while maintaining thread safety in changing datasets. | Notification feeds, real-time dashboards, chat message buffers, or data queues with frequent push/pop operations. |
With these use cases in mind, you're ready to advance your Java skills. upGrad provides courses designed to help you grow and succeed in your career.
Java Vector is a dynamic array that automatically resizes as you add elements and provides built-in thread safety through synchronized methods. To use it effectively, focus on understanding its constructors, capacity management, and key methods for adding, accessing, and removing elements.
Always consider whether thread safety is needed, as Vector's synchronization adds overhead compared to alternatives like ArrayList. Many developers find it challenging to choose Vector over other collections, particularly in multi-threaded environments.
If you're looking to enhance your Java skills, upGrad offers expert guidance with hands-on projects and real-world case studies. The following additional courses from upGrad can also help you succeed.
Ready to take the next step toward becoming an expert in Java Vector? Connect with upGrad for personalized counseling and expert guidance customized to your career goals. For more information, visit your nearest upGrad offline center and start your journey toward excelling in Java vector today!
Boost your career with our popular Software Engineering courses, offering hands-on training and expert guidance to turn you into a skilled software developer.
Master in-demand Software Development skills like coding, system design, DevOps, and agile methodologies to excel in today’s competitive tech industry.
Stay informed with our widely-read Software Development articles, covering everything from coding techniques to the latest advancements in software engineering.
408 articles published
Software Engineering Manager @ upGrad. Passionate about building large scale web apps with delightful experiences. In pursuit of transforming engineers into leaders.
Get Free Consultation
By submitting, I accept the T&C and
Privacy Policy
India’s #1 Tech University
Executive PG Certification in AI-Powered Full Stack Development
77%
seats filled
Top Resources