Vector Class
Overview
- Synchronized (thread-safe) implementation of dynamic array
- Legacy class from Java 1.0
- Implements
Listinterface - Grows automatically as needed
Basic Vector Operations
import java.util.*;
public class VectorBasicExample {
public static void main(String[] args) {
// Creating Vector
Vector<String> vector = new Vector<>();
// Adding elements
vector.add("Apple");
vector.add("Banana");
vector.addElement("Orange"); // Legacy method
vector.add(1, "Mango"); // Insert at specific position
System.out.println("Vector: " + vector);
// Accessing elements
System.out.println("Element at index 0: " + vector.get(0));
System.out.println("First element: " + vector.firstElement());
System.out.println("Last element: " + vector.lastElement());
// Size and capacity
System.out.println("Size: " + vector.size());
System.out.println("Capacity: " + vector.capacity());
// Checking existence
System.out.println("Contains 'Apple': " + vector.contains("Apple"));
System.out.println("Index of 'Banana': " + vector.indexOf("Banana"));
}
}
Vector Constructors
import java.util.*;
public class VectorConstructors {
public static void main(String[] args) {
// 1. Default constructor (capacity: 10)
Vector<Integer> v1 = new Vector<>();
System.out.println("Default capacity: " + v1.capacity());
// 2. With initial capacity
Vector<Integer> v2 = new Vector<>(20);
System.out.println("Capacity 20: " + v2.capacity());
// 3. With initial capacity and capacity increment
Vector<Integer> v3 = new Vector<>(10, 5);
System.out.println("Initial capacity: " + v3.capacity());
// Add elements to see capacity growth
for (int i = 0; i < 15; i++) {
v3.add(i);
}
System.out.println("After adding 15 elements, capacity: " + v3.capacity());
// 4. From existing collection
List<String> list = Arrays.asList("A", "B", "C");
Vector<String> v4 = new Vector<>(list);
System.out.println("Vector from collection: " + v4);
}
}
Vector Capacity Management
import java.util.*;
public class VectorCapacityExample {
public static void main(String[] args) {
Vector<Integer> vector = new Vector<>(5, 3); // Initial: 5, Increment: 3
System.out.println("Initial capacity: " + vector.capacity());
System.out.println("Size: " + vector.size());
// Add elements to trigger capacity increase
for (int i = 1; i <= 10; i++) {
vector.add(i);
System.out.println("Added " + i + " - Size: " + vector.size() +
", Capacity: " + vector.capacity());
}
// Capacity management methods
vector.ensureCapacity(20); // Ensure minimum capacity
System.out.println("After ensureCapacity(20): " + vector.capacity());
vector.trimToSize(); // Trim to current size
System.out.println("After trimToSize(): " + vector.capacity());
}
}
Vector Enumeration (Legacy)
import java.util.*;
public class VectorEnumerationExample {
public static void main(String[] args) {
Vector<String> vector = new Vector<>();
vector.add("Java");
vector.add("Python");
vector.add("C++");
vector.add("JavaScript");
// Using Enumeration (legacy)
System.out.println("Using Enumeration:");
Enumeration<String> enumeration = vector.elements();
while (enumeration.hasMoreElements()) {
System.out.println(enumeration.nextElement());
}
// Using Iterator (modern)
System.out.println("\nUsing Iterator:");
Iterator<String> iterator = vector.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// Using for-each loop
System.out.println("\nUsing for-each:");
for (String language : vector) {
System.out.println(language);
}
// Using forEach with lambda (Java 8+)
System.out.println("\nUsing forEach with lambda:");
vector.forEach(lang -> System.out.println(lang));
}
}
Vector vs ArrayList
import java.util.*;
public class VectorVsArrayList {
public static void main(String[] args) {
// Vector is synchronized
Vector<String> vector = new Vector<>();
vector.add("A");
vector.add("B");
// ArrayList is not synchronized
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("A");
arrayList.add("B");
// Making ArrayList synchronized
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
// Performance comparison
int size = 100000;
// Vector performance
long startTime = System.currentTimeMillis();
Vector<Integer> v = new Vector<>();
for (int i = 0; i < size; i++) {
v.add(i);
}
long vectorTime = System.currentTimeMillis() - startTime;
// ArrayList performance
startTime = System.currentTimeMillis();
ArrayList<Integer> al = new ArrayList<>();
for (int i = 0; i < size; i++) {
al.add(i);
}
long arrayListTime = System.currentTimeMillis() - startTime;
System.out.println("Vector time: " + vectorTime + "ms");
System.out.println("ArrayList time: " + arrayListTime + "ms");
}
}
Thread-Safe Vector Operations
import java.util.*;
public class VectorThreadSafety {
public static void main(String[] args) throws InterruptedException {
Vector<Integer> sharedVector = new Vector<>();
// Create multiple threads that modify the vector
Thread writer1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
sharedVector.add(i);
}
});
Thread writer2 = new Thread(() -> {
for (int i = 1000; i < 2000; i++) {
sharedVector.add(i);
}
});
Thread reader = new Thread(() -> {
// Safe to iterate even while other threads modify
synchronized (sharedVector) {
Iterator<Integer> it = sharedVector.iterator();
while (it.hasNext()) {
System.out.print(it.next() + " ");
}
}
});
writer1.start();
writer2.start();
Thread.sleep(100); // Let writers add some elements
reader.start();
writer1.join();
writer2.join();
reader.join();
System.out.println("\nFinal size: " + sharedVector.size());
}
}
Stack Class
Overview
- LIFO (Last-In-First-Out) data structure
- Extends
Vectorclass - Synchronized (thread-safe)
- Legacy class - Consider using
Dequeinstead for new code
Basic Stack Operations
import java.util.*;
public class StackBasicExample {
public static void main(String[] args) {
// Creating Stack
Stack<String> stack = new Stack<>();
// Pushing elements (adding to top)
stack.push("First");
stack.push("Second");
stack.push("Third");
stack.push("Fourth");
System.out.println("Stack: " + stack);
// Peeking (view top element without removal)
System.out.println("Top element: " + stack.peek());
// Popping elements (removing from top)
System.out.println("Popped: " + stack.pop());
System.out.println("Popped: " + stack.pop());
System.out.println("Stack after pops: " + stack);
// Searching (returns 1-based position from top)
System.out.println("Position of 'First': " + stack.search("First"));
System.out.println("Position of 'Second': " + stack.search("Second")); // -1, not found
// Checking if empty
System.out.println("Is stack empty? " + stack.isEmpty());
// Emptying the stack
while (!stack.isEmpty()) {
System.out.println("Popping: " + stack.pop());
}
System.out.println("Stack empty? " + stack.isEmpty());
}
}
Stack Use Cases
1. Expression Evaluation
import java.util.*;
public class ExpressionEvaluation {
public static boolean isBalanced(String expression) {
Stack<Character> stack = new Stack<>();
for (char ch : expression.toCharArray()) {
if (ch == '(' || ch == '[' || ch == '{') {
stack.push(ch);
} else if (ch == ')' || ch == ']' || ch == '}') {
if (stack.isEmpty()) return false;
char top = stack.pop();
if ((ch == ')' && top != '(') ||
(ch == ']' && top != '[') ||
(ch == '}' && top != '{')) {
return false;
}
}
}
return stack.isEmpty();
}
public static void main(String[] args) {
String[] expressions = {
"((2+3)*5)",
"{[()]}",
"((2+3)*5",
"[(])"
};
for (String expr : expressions) {
System.out.println(expr + " is balanced: " + isBalanced(expr));
}
}
}
2. Undo/Redo Functionality
import java.util.*;
class TextEditor {
private Stack<String> undoStack = new Stack<>();
private Stack<String> redoStack = new Stack<>();
private String currentText = "";
public void write(String text) {
undoStack.push(currentText);
currentText += text;
redoStack.clear(); // Clear redo stack on new write
System.out.println("Text: " + currentText);
}
public void undo() {
if (!undoStack.isEmpty()) {
redoStack.push(currentText);
currentText = undoStack.pop();
System.out.println("Undo - Text: " + currentText);
} else {
System.out.println("Nothing to undo");
}
}
public void redo() {
if (!redoStack.isEmpty()) {
undoStack.push(currentText);
currentText = redoStack.pop();
System.out.println("Redo - Text: " + currentText);
} else {
System.out.println("Nothing to redo");
}
}
}
public class UndoRedoExample {
public static void main(String[] args) {
TextEditor editor = new TextEditor();
editor.write("Hello");
editor.write(" World");
editor.write("!");
editor.undo();
editor.undo();
editor.redo();
editor.redo();
}
}
3. Browser History
import java.util.*;
class Browser {
private Stack<String> backStack = new Stack<>();
private Stack<String> forwardStack = new Stack<>();
private String currentPage = "home";
public void visit(String url) {
backStack.push(currentPage);
currentPage = url;
forwardStack.clear(); // Clear forward stack on new visit
System.out.println("Visited: " + currentPage);
}
public void back() {
if (!backStack.isEmpty()) {
forwardStack.push(currentPage);
currentPage = backStack.pop();
System.out.println("Back to: " + currentPage);
} else {
System.out.println("Can't go back");
}
}
public void forward() {
if (!forwardStack.isEmpty()) {
backStack.push(currentPage);
currentPage = forwardStack.pop();
System.out.println("Forward to: " + currentPage);
} else {
System.out.println("Can't go forward");
}
}
public String getCurrentPage() {
return currentPage;
}
}
public class BrowserHistoryExample {
public static void main(String[] args) {
Browser browser = new Browser();
browser.visit("google.com");
browser.visit("github.com");
browser.visit("stackoverflow.com");
browser.back();
browser.back();
browser.forward();
browser.visit("leetcode.com");
browser.forward(); // Can't go forward after new visit
}
}
Stack with Custom Objects
import java.util.*;
class Book {
private String title;
private String author;
private int year;
public Book(String title, String author, int year) {
this.title = title;
this.author = author;
this.year = year;
}
public String getTitle() { return title; }
public String getAuthor() { return author; }
public int getYear() { return year; }
@Override
public String toString() {
return title + " by " + author + " (" + year + ")";
}
}
public class StackWithObjects {
public static void main(String[] args) {
Stack<Book> bookStack = new Stack<>();
// Push books onto stack
bookStack.push(new Book("Effective Java", "Joshua Bloch", 2018));
bookStack.push(new Book("Clean Code", "Robert Martin", 2008));
bookStack.push(new Book("Head First Java", "Kathy Sierra", 2005));
System.out.println("Books in stack (LIFO order):");
// Process books in LIFO order
while (!bookStack.isEmpty()) {
Book book = bookStack.pop();
System.out.println("Processing: " + book);
}
}
}
Modern Alternative to Stack
import java.util.*;
public class DequeAsStack {
public static void main(String[] args) {
// Using ArrayDeque as stack (recommended for new code)
Deque<String> stack = new ArrayDeque<>();
// Push operations
stack.push("First");
stack.push("Second");
stack.push("Third");
System.out.println("Stack: " + stack);
// Peek operation
System.out.println("Top element: " + stack.peek());
// Pop operations
System.out.println("Popped: " + stack.pop());
System.out.println("Popped: " + stack.pop());
System.out.println("Remaining: " + stack);
// Additional Deque operations
stack.addLast("New Last"); // Equivalent to push for stack behavior
stack.addFirst("New First");
System.out.println("After additions: " + stack);
}
}
Complete Stack Implementation Example
import java.util.*;
public class CompleteStackExample {
// Method to reverse a list using stack
public static <T> List<T> reverseList(List<T> list) {
Stack<T> stack = new Stack<>();
List<T> reversed = new ArrayList<>();
// Push all elements onto stack
for (T element : list) {
stack.push(element);
}
// Pop elements to get reversed order
while (!stack.isEmpty()) {
reversed.add(stack.pop());
}
return reversed;
}
// Method to check palindrome using stack
public static boolean isPalindrome(String str) {
Stack<Character> stack = new Stack<>();
String cleanStr = str.replaceAll("[^a-zA-Z0-9]", "").toLowerCase();
// Push first half of characters
for (int i = 0; i < cleanStr.length() / 2; i++) {
stack.push(cleanStr.charAt(i));
}
// Start from middle (adjust for odd length)
int startIndex = cleanStr.length() / 2;
if (cleanStr.length() % 2 != 0) {
startIndex++;
}
// Compare with second half
for (int i = startIndex; i < cleanStr.length(); i++) {
if (stack.pop() != cleanStr.charAt(i)) {
return false;
}
}
return true;
}
public static void main(String[] args) {
// Test reverse list
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Diana");
System.out.println("Original: " + names);
System.out.println("Reversed: " + reverseList(names));
// Test palindrome
String[] testStrings = {"racecar", "hello", "A man a plan a canal Panama"};
for (String str : testStrings) {
System.out.println("'" + str + "' is palindrome: " + isPalindrome(str));
}
}
}
Key Points to Remember
Vector:
- Synchronized - Thread-safe but slower than ArrayList
- Dynamic array - Grows automatically
- Legacy class - Use ArrayList for better performance in single-threaded environments
- Capacity management - Can specify initial capacity and increment
Stack:
- LIFO principle
- Extends Vector - Inherits all Vector methods
- Legacy class - Use Deque interface with ArrayDeque for better performance
- Common use cases: Expression evaluation, undo/redo, backtracking
When to Use:
- Vector: When thread safety is needed and performance is not critical
- Stack: When LIFO behavior is required in legacy code
- Alternatives: Use
Collections.synchronizedList()orCopyOnWriteArrayListfor thread safety, andArrayDequefor stack operations
Both Vector and Stack are legacy classes and generally not recommended for new code, but they're important to understand for maintaining existing applications.