背景
在并发编程学习中,遇到了一个之前没用过的类vector,于是去搜索了下,没想到已经不推荐使用了,但还是记录下吧
什么是vector
Vector 是 Java 标准库中的一个类,位于 java.util 包中。它是一个动态数组(类似于 ArrayList),但与 ArrayList 不同的是,Vector 是线程安全的。这意味着 Vector 的所有方法都是同步的(即加了 synchronized 关键字),可以在多线程环境中安全使用,而不会出现数据不一致的问题。
1. Vector 的基本特性
动态数组:Vector 是一个可以动态增长和缩小的数组。你可以像操作普通数组一样对 Vector 进行增删查改操作,但它可以根据需要自动调整大小。
线程安全:Vector 的所有方法都是同步的,确保在多线程环境下对 Vector 的访问是安全的。每个方法都会对整个对象进行加锁,防止多个线程同时修改 Vector 的内容。
性能较低:由于 Vector 的所有方法都是同步的,这使得它的性能比 ArrayList 更低,尤其是在高并发场景下。每次调用 Vector 的方法时,JVM 都会进行锁的获取和释放操作,这会导致一定的性能开销。
过时的 API:虽然 Vector 仍然存在于 Java 中,但它已经被认为是一个过时的类。Java 官方推荐使用 ArrayList 或 CopyOnWriteArrayList 等更现代的集合类来替代 Vector。如果你需要线程安全的集合,CopyOnWriteArrayList 或者 Collections.synchronizedList() 提供了更好的性能和灵活性。
2. Vector 的常用方法
Vector 提供了许多与 ArrayList 类似的常用方法,以下是一些常见的操作:
构造函数:
Vector():创建一个空的 Vector,初始容量为 10。
Vector(int capacity):创建一个指定初始容量的 Vector。
Vector(int capacity, int capacityIncrement):创建一个指定初始容量和容量增量的 Vector。当 Vector 的容量不足时,会根据 capacityIncrement 增加容量。
Vector(Collection<? extends E> c):创建一个包含指定集合元素的 Vector。
添加元素:
add(E e):将指定的元素添加到 Vector 的末尾。
addElement(E e):这是 Vector 特有的方法,功能与 add() 相同。
insertElementAt(E obj, int index):在指定位置插入元素。
删除元素:
remove(int index):删除指定位置的元素。
removeElement(Object obj):删除第一个匹配的元素。
removeAllElements():清空 Vector 中的所有元素。
获取元素:
get(int index):返回指定位置的元素。
elementAt(int index):这是 Vector 特有的方法,功能与 get() 相同。
firstElement():返回 Vector 的第一个元素。
lastElement():返回 Vector 的最后一个元素。
查找元素:
indexOf(Object o):返回指定元素第一次出现的位置,如果不存在则返回 -1。
lastIndexOf(Object o):返回指定元素最后一次出现的位置,如果不存在则返回 -1。
遍历元素:
iterator():返回一个迭代器,用于遍历 Vector 中的元素。
listIterator():返回一个列表迭代器,支持双向遍历。
容量管理:
capacity():返回 Vector 的当前容量。
ensureCapacity(int minCapacity):确保 Vector 的容量至少为指定值。
trimToSize():将 Vector 的容量调整为当前元素的数量。
3. Vector 的线程安全性
Vector 的线程安全性是通过在其方法上添加 synchronized 关键字实现的。例如,add() 方法的实现如下:
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
可以看到,add() 方法是同步的,这意味着在同一时间只有一个线程可以执行该方法。这种同步机制确保了多个线程在并发访问 Vector 时不会发生数据竞争或不一致的问题。
然而,这种同步机制也带来了性能上的开销。每次调用 Vector 的方法时,JVM 都会进行锁的获取和释放操作,这会导致一定的性能下降。因此,在单线程或低并发场景下,Vector 的性能不如 ArrayList。
4. Vector 与 ArrayList 的比较
特性 | Vector | ArrayList |
---|---|---|
线程安全性 | 所有方法都是同步的,线程安全 | 所有方法都不是同步的,非线程安全 |
性能 | 由于同步,性能较低 | 无同步开销,性能较高 |
容量增长 | 每次扩容时增加 capacityIncrement | 每次扩容时增加 50% |
过时程度 | 被认为是过时的类,官方推荐使用其他集合类 | 现代集合类,广泛使用 |
适用场景 | 多线程环境下的集合操作 | 单线程或低并发环境下的集合操作 |
5. 替代方案
由于 Vector 的性能问题和过时的设计,Java 官方推荐使用以下几种替代方案:
ArrayList:如果你不需要线程安全的集合,ArrayList 是更好的选择。它提供了更高的性能,并且可以通过 Collections.synchronizedList() 来实现线程安全。
List<String> list = Collections.synchronizedList(new ArrayList<>());
CopyOnWriteArrayList:如果你需要线程安全的集合,并且读操作远多于写操作,CopyOnWriteArrayList 是一个不错的选择。它在每次写操作时都会复制整个数组,因此写操作的代价较大,但在读操作时不需要加锁,性能较好。
List<String> list = new CopyOnWriteArrayList<>();
ConcurrentHashMap:如果你需要一个线程安全的哈希表,ConcurrentHashMap 是一个高性能的选择。它使用分段锁机制,允许多个线程同时进行读写操作。
6. 总结
Vector 是一个线程安全的动态数组,适用于多线程环境下的集合操作。然而,由于其性能较低且设计过时,Java 官方推荐使用 ArrayList 或其他更现代的集合类来替代 Vector。如果你确实需要线程安全的集合,可以考虑使用 Collections.synchronizedList() 或 CopyOnWriteArrayList 等替代方案。