Java Vector集合全面解析:线程安全的动态数组
一、Vector集合概述
1.1 Vector的历史地位
Vector是Java集合框架中的元老级类,自JDK 1.0就已存在。它是早期Java版本中重要的动态数组实现,虽然现在已不推荐在新项目中使用,但理解其特性对于掌握Java集合框架的演进历程具有重要意义。
1.2 Vector的核心定位
Vector是一个线程安全的动态数组实现,它通过在方法级别添加synchronized关键字来保证多线程环境下的数据安全。
二、Vector集合核心特点
2.1 数据结构特性
- 底层结构:基于动态数组实现
- 索引访问:支持通过索引直接访问元素
- 性能特征:查询速度快,增删操作相对较慢
- 线程安全:所有公共方法都是同步的
2.2 与ArrayList的对比
特性 | Vector | ArrayList |
线程安全 | 是(同步方法) | 否 |
性能 | 相对较低(同步开销) | 相对较高 |
扩容策略 | 默认2倍增长 | 默认1.5倍增长 |
历史版本 | JDK 1.0 | JDK 1.2 |
推荐使用 | 不推荐 | 推荐 |
三、Vector集合实战详解
3.1 创建Vector实例
import java.util.Vector;public class VectorCreation {public static void main(String[] args) {System.out.println("=== Vector创建方式演示 ===");// 1. 创建空的Vector(默认容量10)Vector<String> vector1 = new Vector<>();System.out.println("空Vector容量: " + vector1.capacity());// 2. 创建指定初始容量的VectorVector<Integer> vector2 = new Vector<>(15);System.out.println("指定容量Vector: " + vector2.capacity());// 3. 创建指定初始容量和容量增量的VectorVector<Double> vector3 = new Vector<>(10, 5);System.out.println("带增量Vector初始容量: " + vector3.capacity());// 添加元素测试扩容for (int i = 0; i < 12; i++) {vector3.add(i * 1.0);}System.out.println("扩容后容量: " + vector3.capacity());}
}3.2 元素添加操作
public class VectorAddOperations {public static void main(String[] args) {Vector<String> vector = new Vector<>();System.out.println("=== Vector添加操作演示 ===");// 基本添加方法vector.add("Apple");vector.add("Banana");// Vector特有的添加方法vector.addElement("Cherry");vector.addElement("Orange");System.out.println("添加后Vector: " + vector);// 指定位置插入vector.add(1, "Blueberry");System.out.println("指定位置插入后: " + vector);// 批量添加Vector<String> fruits = new Vector<>();fruits.add("Grape");fruits.add("Mango");vector.addAll(fruits);System.out.println("批量添加后: " + vector);}
}3.3 元素访问操作
public class VectorAccessOperations {public static void main(String[] args) {Vector<String> vector = new Vector<>();vector.add("Apple");vector.add("Banana");vector.add("Cherry");vector.add("Orange");System.out.println("=== Vector访问操作演示 ===");// 通过索引访问String fruit1 = vector.get(1);System.out.println("索引1的元素: " + fruit1);// Vector特有的访问方法String fruit2 = vector.elementAt(2);System.out.println("elementAt(2): " + fruit2);// 获取首尾元素String first = vector.firstElement();String last = vector.lastElement();System.out.println("首元素: " + first + ", 尾元素: " + last);// 获取子列表List<String> subList = vector.subList(1, 3);System.out.println("子列表: " + subList);}
}3.4 元素修改操作
public class VectorUpdateOperations {public static void main(String[] args) {Vector<String> vector = new Vector<>();vector.add("Apple");vector.add("Banana");vector.add("Cherry");System.out.println("=== Vector修改操作演示 ===");System.out.println("修改前: " + vector);// 修改指定位置元素String oldValue = vector.set(1, "Blueberry");System.out.println("被替换的值: " + oldValue);System.out.println("修改后: " + vector);// 使用setElementAt方法vector.setElementAt("Strawberry", 2);System.out.println("setElementAt后: " + vector);}
}3.5 元素删除操作
public class VectorRemoveOperations {public static void main(String[] args) {Vector<String> vector = new Vector<>();vector.add("Apple");vector.add("Banana");vector.add("Cherry");vector.add("Orange");vector.add("Banana"); // 重复元素System.out.println("=== Vector删除操作演示 ===");System.out.println("初始Vector: " + vector);// 按索引删除String removed1 = vector.remove(1);System.out.println("删除索引1的元素: " + removed1);System.out.println("删除后: " + vector);// 按元素值删除(首次出现)boolean removed2 = vector.remove("Banana");System.out.println("按值删除是否成功: " + removed2);System.out.println("删除后: " + vector);// Vector特有的删除方法vector.removeElement("Orange");System.out.println("removeElement后: " + vector);// 删除所有元素vector.clear();System.out.println("clear后: " + vector);System.out.println("是否为空: " + vector.isEmpty());}
}3.6 容量与大小管理
public class VectorCapacityManagement {public static void main(String[] args) {Vector<Integer> vector = new Vector<>(5, 3);System.out.println("=== Vector容量管理演示 ===");// 初始状态System.out.println("初始容量: " + vector.capacity());System.out.println("初始大小: " + vector.size());System.out.println("是否为空: " + vector.isEmpty());// 添加元素for (int i = 1; i <= 7; i++) {vector.add(i);}System.out.println("添加7个元素后:");System.out.println("容量: " + vector.capacity()); // 扩容后的容量System.out.println("大小: " + vector.size());// 容量调整vector.trimToSize();System.out.println("trimToSize后容量: " + vector.capacity());// 确保容量vector.ensureCapacity(20);System.out.println("ensureCapacity(20)后容量: " + vector.capacity());}
}3.7 多种遍历方式
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;public class VectorTraversal {public static void main(String[] args) {Vector<String> vector = new Vector<>();vector.add("Apple");vector.add("Banana");vector.add("Cherry");vector.add("Orange");System.out.println("=== Vector遍历方式演示 ===");// 1. 传统for循环System.out.println("1. 传统for循环:");for (int i = 0; i < vector.size(); i++) {System.out.println("索引 " + i + ": " + vector.get(i));}// 2. 增强for循环System.out.println("\n2. 增强for循环:");for (String fruit : vector) {System.out.println("元素: " + fruit);}// 3. 迭代器遍历System.out.println("\n3. 迭代器遍历:");Iterator<String> iterator = vector.iterator();while (iterator.hasNext()) {System.out.println("元素: " + iterator.next());}// 4. Vector特有的Enumeration遍历System.out.println("\n4. Enumeration遍历:");Enumeration<String> enumeration = vector.elements();while (enumeration.hasMoreElements()) {System.out.println("元素: " + enumeration.nextElement());}// 5. forEach方法(Java 8+)System.out.println("\n5. forEach方法:");vector.forEach(fruit -> System.out.println("元素: " + fruit));}
}3.8 搜索与检查操作
public class VectorSearchOperations {public static void main(String[] args) {Vector<String> vector = new Vector<>();vector.add("Apple");vector.add("Banana");vector.add("Cherry");vector.add("Banana");vector.add("Orange");System.out.println("=== Vector搜索操作演示 ===");// 元素存在性检查boolean containsApple = vector.contains("Apple");System.out.println("是否包含Apple: " + containsApple);// 查找元素索引int firstIndex = vector.indexOf("Banana");int lastIndex = vector.lastIndexOf("Banana");System.out.println("Banana第一次出现位置: " + firstIndex);System.out.println("Banana最后一次出现位置: " + lastIndex);// 从指定位置开始搜索int indexFrom = vector.indexOf("Banana", 2);System.out.println("从位置2开始搜索Banana: " + indexFrom);// 检查包含所有元素Vector<String> checkList = new Vector<>();checkList.add("Apple");checkList.add("Cherry");boolean containsAll = vector.containsAll(checkList);System.out.println("是否包含所有检查元素: " + containsAll);}
}3.9 数组转换操作
public class VectorArrayConversion {public static void main(String[] args) {Vector<String> vector = new Vector<>();vector.add("Apple");vector.add("Banana");vector.add("Cherry");System.out.println("=== Vector数组转换演示 ===");// 转换为Object数组Object[] objectArray = vector.toArray();System.out.println("Object数组:");for (Object obj : objectArray) {System.out.println(obj);}// 转换为指定类型数组String[] stringArray = vector.toArray(new String[0]);System.out.println("String数组:");for (String str : stringArray) {System.out.println(str);}// 使用指定大小的数组String[] sizedArray = vector.toArray(new String[vector.size()]);System.out.println("指定大小数组长度: " + sizedArray.length);}
}3.10 线程安全演示
public class VectorThreadSafety {public static void main(String[] args) throws InterruptedException {System.out.println("=== Vector线程安全演示 ===");Vector<Integer> sharedVector = new Vector<>();// 创建任务:向Vector中添加元素Runnable addTask = () -> {String threadName = Thread.currentThread().getName();for (int i = 0; i < 50; i++) {sharedVector.add(i);System.out.println(threadName + " 添加: " + i);try {Thread.sleep(10); // 模拟处理时间} catch (InterruptedException e) {e.printStackTrace();}}};// 创建多个线程同时操作VectorThread thread1 = new Thread(addTask, "线程-1");Thread thread2 = new Thread(addTask, "线程-2");Thread thread3 = new Thread(addTask, "线程-3");thread1.start();thread2.start();thread3.start();// 等待所有线程完成thread1.join();thread2.join();thread3.join();System.out.println("最终Vector大小: " + sharedVector.size());System.out.println("预期大小: 150, 实际大小: " + sharedVector.size());System.out.println("数据一致性: " + (sharedVector.size() == 150));}
}四、List集合总结
4.1 List接口核心特性
有序性保证
- 严格保持元素的插入顺序
- 每个元素有确定的索引位置(0-based)
元素可重复性
- 允许存储重复元素
- 通过equals()方法判断元素相等性
索引操作支持
- 支持通过索引直接访问、插入、删除元素
- 提供丰富的基于索引的操作方法
4.2 三大List实现类对比
特性 | ArrayList | LinkedList | Vector |
底层结构 | 动态数组 | 双向链表 | 动态数组 |
线程安全 | 否 | 否 | 是 |
查询性能 | O(1) | O(n) | O(1) |
增删性能 | O(n) | O(1) | O(n) |
内存占用 | 较小 | 较大 | 较小 |
扩容策略 | 1.5倍 | 无 | 2倍 |
推荐使用 | 推荐 | 特定场景 | 不推荐 |
4.3 选择指南
选择ArrayList:
- 大部分操作是查询
- 单线程环境
- 内存使用敏感的场景
选择LinkedList:
- 频繁在头部插入删除
- 需要实现队列或栈
- 元素数量变化大
选择Vector:
- 遗留系统维护
- 简单的多线程场景
- 不需要高性能要求的线程安全
4.4 最佳实践建议
- 优先使用ArrayList:在大多数场景下是最佳选择
- 线程安全方案:使用Collections.synchronizedList()包装ArrayList
- 容量规划:预先估算数据量,设置合适的初始容量
- 遍历选择:根据具体需求选择合适的遍历方式
- 泛型使用:始终使用泛型保证类型安全
总结
Vector作为Java集合框架的历史遗留类,虽然在新项目中不推荐使用,但理解其特性和实现原理对于深入掌握Java集合框架具有重要意义。通过本文的详细解析,读者应该能够全面理解Vector的工作原理、使用方法以及与其他List实现类的区别,从而在实际开发中做出更加明智的技术选型。
在大多数现代Java应用中,ArrayList配合适当的同步机制通常是更好的选择。
