ArrayList和Vector之间有哪些主要区别?
参考回答**
ArrayList
和 Vector
是 Java 中基于动态数组实现的两个常用集合类,但它们之间有以下主要区别:
特性 | ArrayList | Vector |
---|---|---|
线程安全性 | 非线程安全:不支持同步,需手动实现线程安全。 | 线程安全:所有方法都被同步(synchronized )。 |
性能 | 由于没有同步开销,性能高于 Vector 。 |
由于方法同步,性能比 ArrayList 低。 |
扩容方式 | 每次扩容为 原容量的 1.5 倍。 | 每次扩容为 原容量的 2 倍。 |
迭代器 | 使用 Iterator ,是 fail-fast 的。 |
使用 Enumeration 和 Iterator ,Enumeration 是 fail-safe 的。 |
使用场景 | 适合单线程环境,效率高。 | 适合多线程环境,但性能较低,已较少使用。 |
详细讲解与扩展
1. 线程安全性
ArrayList
:- ArrayList是非线程安全的,多个线程同时访问时需要手动同步:
List<Integer> synchronizedList = Collections.synchronizedList(new ArrayList<>());
Vector
:Vector
的所有方法都被同步(synchronized
)修饰,因此是线程安全的。但由于加锁操作,其性能较低。
2. 扩容机制
ArrayList
:- 默认容量为 10,扩容时新容量为 原容量的 1.5 倍:
newCapacity = oldCapacity + (oldCapacity >> 1);
- 这样可以减少扩容次数,节省内存和性能开销。
Vector
:- 默认容量为 10,扩容时新容量为 原容量的 2 倍。
- 由于扩容倍数更大,可能会浪费内存。
示例对比:
ArrayList<Integer> arrayList = new ArrayList<>(10); // 默认初始容量 10
Vector<Integer> vector = new Vector<>(10); // 默认初始容量 10
// 添加 15 个元素,触发扩容
for (int i = 0; i < 15; i++) {
arrayList.add(i);
vector.add(i);
}
// ArrayList 容量变为 15(10 → 15)
// Vector 容量变为 20(10 → 20)
3. 迭代器类型
ArrayList
:- 主要使用
Iterator
迭代。 - 是 fail-fast 的,即在迭代过程中,如果检测到集合被结构性修改(如添加或删除元素),会抛出
ConcurrentModificationException
。
- 主要使用
Vector
:- 可以使用
Enumeration
或Iterator
迭代: Enumeration
是 fail-safe 的,不会抛出异常,但功能有限(不支持删除元素)。Iterator
是 fail-fast 的。
- 可以使用
示例:
Vector<String> vector = new Vector<>();
vector.add("A");
vector.add("B");
// 使用 Enumeration 迭代
Enumeration<String> enumeration = vector.elements();
while (enumeration.hasMoreElements()) {
System.out.println(enumeration.nextElement());
}
// 使用 Iterator 迭代
Iterator<String> iterator = vector.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
4. 性能对比
ArrayList
:- 因为没有线程安全机制,所以性能高于
Vector
。 - 适合单线程环境或使用外部同步控制的多线程环境。
- 因为没有线程安全机制,所以性能高于
Vector
:- 由于加锁(同步)机制的存在,性能较低。
- 适合多线程环境,但已逐渐被更高效的并发类(如
CopyOnWriteArrayList
)取代。
5. 使用场景
ArrayList
:- 用于单线程场景。
- 如果需要线程安全,建议使用
Collections.synchronizedList()
或并发包中的CopyOnWriteArrayList
。
Vector
:- 由于其同步机制和过时的设计,现代开发中很少直接使用。
- 在多线程场景中,建议使用
CopyOnWriteArrayList
或其他线程安全的集合类代替。
6. 示例代码对比
ArrayList 示例:
import java.util.ArrayList;
public class ArrayListExample {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
// 遍历列表
for (String s : list) {
System.out.println(s);
}
}
}
Vector 示例:
import java.util.Vector;
public class VectorExample {
public static void main(String[] args) {
Vector<String> vector = new Vector<>();
vector.add("A");
vector.add("B");
vector.add("C");
// 使用 Enumeration 遍历
Enumeration<String> enumeration = vector.elements();
while (enumeration.hasMoreElements()) {
System.out.println(enumeration.nextElement());
}
}
}
总结
特性 | ArrayList | Vector |
---|---|---|
线程安全性 | 非线程安全,需要手动同步。 | 线程安全(同步),性能较低。 |
扩容方式 | 原容量的 1.5 倍,减少内存浪费。 | 原容量的 2 倍,可能浪费更多内存。 |
迭代器 | 使用 Iterator ,是 fail-fast 的。 |
使用 Enumeration 或 Iterator 。 |
性能 | 性能较高,适合单线程场景。 | 性能较低,适合多线程,但已较少使用。 |
推荐使用场景 | 单线程场景或外部同步控制的多线程场景。 | 多线程场景,但更推荐使用 CopyOnWriteArrayList 。 |
在现代 Java 开发中,ArrayList
更常用,而 Vector
已逐渐被弃用。如果需要线程安全的动态数组,建议使用 CopyOnWriteArrayList
替代。