Why Vector Is Legacy in Java and What Replaced It
Fast recall
Quick revision
Core answer
Vector is a legacy list whose core operations use synchronization. It is not a complete answer to concurrent workflows because a sequence of individually synchronized calls is not automatically atomic. Use ArrayList when access is confined, a synchronized wrapper with the required external locking for simple shared use, or a concurrent structure such as CopyOnWriteArrayList when its read-heavy copy-on-write trade-off fits.Understanding of Java's evolution from coarse-grained synchronization to modern concurrency utilities and knowing when thread safety is actually needed
Believing Vector is a safe thread-safe choice — its method-level synchronization is insufficient for compound operations and causes unnecessary contention
Explain that Vector's synchronization is at the method level, so operations like "check if empty, then get first element" still require external synchronization
Interview-ready guide
Interview answer
Vector is considered legacy because it builds synchronization into many core list operations even when callers do not need sharing, while a multi-call action is still not automatically atomic. For example, another thread can change the vector between an emptiness check and a later removal unless the whole sequence uses the same lock.
I use ArrayList for confined or externally protected data. A synchronizedList wrapper can fit simple shared access, provided iteration and compound actions synchronize on the wrapper as documented. CopyOnWriteArrayList fits a small, read-heavy list where snapshot iteration is useful and writes are rare, because every successful write copies the backing array. There is no universal replacement without knowing the access pattern.
Why Vector Is Legacy in Java and What Replaced It
Direct Answer
Vector is a legacy list whose core operations use synchronization. It is not a complete answer to concurrent workflows because a sequence of individually synchronized calls is not automatically atomic. Use ArrayList when access is confined, a synchronized wrapper with the required external locking for simple shared use, or a concurrent structure such as CopyOnWriteArrayList when its read-heavy copy-on-write trade-off fits.
Code Example
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class VectorReplacementDemo {
public static void main(String[] args) {
// Legacy: Vector (synchronized, avoid in new code)
Vector<String> legacy = new Vector<>();
legacy.add("Order-1"); // acquires a lock
// Modern single-threaded: ArrayList
List<String> orders = new ArrayList<>();
orders.add("Order-1"); // no lock overhead
// Multi-threaded basic: synchronizedList (still needs external lock for compound ops)
List<String> sync = Collections.synchronizedList(new ArrayList<>());
synchronized (sync) {
if (!sync.isEmpty()) {
String first = sync.get(0); // safe inside the block
}
}
// Read-heavy concurrent: CopyOnWriteArrayList
List<String> concurrent = new CopyOnWriteArrayList<>();
concurrent.add("Order-1"); // locks only for the write
String read = concurrent.get(0); // reads never block
}
}
Common Mistakes & Pitfalls
- Assuming synchronized methods make a workflow atomic: several calls still need one common lock or an atomic API.
- Forgetting synchronized-wrapper iteration rules: synchronize on the returned wrapper while traversing it.
- Using copy-on-write for frequent writes: each successful update copies the backing array.
- Assuming request code cannot share data: local variables are separate, but referenced objects or fields may still be shared.
Check your understanding
Answer these without looking back at the article.
- What is CopyOnWriteArrayList and when would you use it?
- Is Collections.synchronizedList truly thread-safe for all operations?
- What is the modern replacement for Stack in Java?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.