java基础-Vector(向量)

Vector 是 Java 中一个经典的集合类,它是动态数组 的实现,位于 java.util 包中。虽然在现代 Java 开发中它已不是首选,但理解它的特性和历史背景仍然很重要。

Java的 Vector 类拥有一个清晰的继承与实现层次。它的完整声明如下:

java 复制代码
public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

下面这个表格可以帮你快速了解 Vector 的整个"家谱"结构。

类别 类/接口 与 Vector 的关系 核心作用
父类 AbstractList 继承 提供了 List 接口的骨架实现,如 get、add、remove 等方法的基本逻辑。
核心接口 List 实现 定义了有序集合(序列)的标准契约,是 Vector 作为动态数组的核心依据。
标记接口 RandomAccess 实现 标记接口 ,表明 Vector 支持高效(常数时间)的随机访问(如 get(i))。
Cloneable 实现 标记接口 ,表明 Vector 实例可以被 clone() 方法复制。
Serializable 实现 标记接口 ,表明 Vector 可以被序列化(可转化为字节流用于网络传输或持久化存储)。

整体架构图

从 Object 类开始的完整单继承链是:Object → AbstractCollection → AbstractList → Vector。

接口与实现的要点解析

了解这些接口和父类,能帮助你理解 Vector 的行为:

  • 线程安全的基石 :虽然线程安全不是通过某个特定接口定义的,但它是 Vector 区别于 ArrayList 最关键的实现细节。它的核心操作方法(如 add, remove, get)都使用 synchronized 关键字修饰,保证了多线程环境下的数据安全,但也带来了性能开销。

  • RandomAccess 的实际影响 :实现这个标记接口意味着像 Collections.binarySearch() 这样的算法在处理 Vector 时,会优先使用效率更高的基于索引的随机访问,而不是迭代器。

核心特性

1. 同步/线程安全

Vector 的所有主要方法都使用 synchronized 关键字修饰,因此是线程安全的。

java 复制代码
// 线程安全示例
Vector<String> vector = new Vector<>();
// 以下操作在多线程环境下是安全的
vector.add("Item1");
vector.get(0);

2. 动态扩容

当容量不足时,Vector 会自动增长:

  • 默认初始容量:10

  • 默认增长策略:容量翻倍(可自定义)

java 复制代码
Vector<Integer> v = new Vector<>(5, 3); // 初始容量5,每次增加3
for (int i = 0; i < 10; i++) {
    v.add(i);
    System.out.println("Size: " + v.size() + ", Capacity: " + v.capacity());
}

3. 遗留类

Vector 是 Java 1.0 就存在的类,后来为了更好的集合框架设计,在 Java 1.2 中引入了 Collection 框架。

与 ArrayList 的对比

特性 Vector ArrayList
线程安全 是(同步方法) 否
性能 较慢(同步开销) 较快
扩容策略 默认翻倍(可自定义增量) 默认增加50%
迭代器 fail-fast(快速失败) fail-fast
Java版本 1.0 1.2

基本用法示例

java 复制代码
import java.util.*;

public class VectorExample {
    public static void main(String[] args) {
        // 创建 Vector
        Vector<String> fruits = new Vector<>();
        
        // 添加元素
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.addElement("Cherry"); // 遗留方法
        
        // 获取元素
        System.out.println(fruits.get(0));      // Apple
        System.out.println(fruits.elementAt(1)); // 遗留方法: Banana
        
        // 遍历
        // 1. 使用迭代器
        Iterator<String> it = fruits.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
        
        // 2. 使用 Enumeration(遗留方式)
        Enumeration<String> en = fruits.elements();
        while (en.hasMoreElements()) {
            System.out.println(en.nextElement());
        }
        
        // 容量相关操作
        System.out.println("Size: " + fruits.size());       // 当前元素数量
        System.out.println("Capacity: " + fruits.capacity()); // 当前容量
        
        fruits.ensureCapacity(20);  // 确保最小容量
        fruits.trimToSize();        // 将容量调整为当前大小
    }
}

线程安全示例

java 复制代码
import java.util.Vector;

public class ThreadSafeExample {
    private static Vector<Integer> vector = new Vector<>();
    
    public static void main(String[] args) throws InterruptedException {
        // 创建多个线程同时修改 Vector
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                vector.add(i);
            }
        });
        
        Thread t2 = new Thread(() -> {
            for (int i = 1000; i < 2000; i++) {
                vector.add(i);
            }
        });
        
        t1.start();
        t2.start();
        
        t1.join();
        t2.join();
        
        // 不会出现并发问题
        System.out.println("Vector size: " + vector.size()); // 应该是2000
    }
}

现代替代方案

1. 使用 ArrayList + 同步包装

java 复制代码
// 替代 Vector 的线程安全方案
List<String> syncList = Collections.synchronizedList(new ArrayList<>());

// 或者在并发场景下使用
List<String> concurrentList = new CopyOnWriteArrayList<>();

2. 并发集合类

java 复制代码
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ConcurrentLinkedQueue;

// 高并发读取场景
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();

// 并发队列
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();

使用建议

使用 Vector 的场景

  1. 维护遗留代码

  2. 简单的多线程共享集合(但现代方案更好)

避免使用 Vector 的场景

  1. 新开发的项目

  2. 单线程环境(使用 ArrayList)

  3. 高并发环境(使用 java.util.concurrent 包中的类)

重要方法总结

java 复制代码
// 添加元素
add(E e)             // 添加元素
addElement(E obj)    // 遗留方法
insertElementAt(E obj, int index)

// 获取元素
get(int index)
elementAt(int index) // 遗留方法
firstElement()
lastElement()

// 删除元素
remove(int index)
removeElement(Object obj)
clear()

// 容量管理
ensureCapacity(int minCapacity)
trimToSize()
setSize(int newSize)  // 可能填充null或截断

// 搜索
contains(Object o)
indexOf(Object o)

// 枚举器(遗留)
elements()  // 返回 Enumeration

性能考虑

由于 Vector 的方法都是同步的,在多线程竞争激烈的情况下,性能会受到影响。现代 Java 提供了更精细的并发控制机制:

java 复制代码
// 更好的多线程方案
List<String> list = new ArrayList<>();
// 只在必要时同步
synchronized(list) {
    list.add("item");
}

总结 :虽然 Vector 在 Java 历史上占有重要地位,但在现代开发中,ArrayList 和 java.util.concurrent 包中的并发集合通常是更好的选择。理解 Vector 有助于维护遗留代码,但在新项目中应优先考虑更现代的替代方案。

相关推荐
Moshow郑锴2 小时前
sql-pipeline - 基于PostgreSQL的SQL健康检查与发布编排平台
java·sql
Wang's Blog9 小时前
Java 项目实战: 外卖平台优化-Nginx配置文件结构与块层级
java·开发语言·nginx
\光辉岁月/10 小时前
5.java-数组
java·开发语言
谢亮_vipxieliang11 小时前
Spring 事务失效的常见场景
java·开发语言·数据库·spring boot
郑州光合科技余经理11 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
2601_9620715711 小时前
类变量和全局变量的生命周期有什么区别?
java·开发语言·jvm
code2cat11 小时前
Java进阶篇之AtomicReference:一次替换引用,读到一份完整状态
java·并发编程·不可变对象·atomicreference
专业程序开发源11 小时前
springboot简历管理系统81389-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·php·课程设计
Wang's Blog11 小时前
Java 项目实战: 外卖平台优化-前后端分离开发模式与工程拆分
java·开发语言
HEJOO912 小时前
指针的算术运算详解
java·数据结构·算法