深入浅出Vector

本章是整理知识内容,为强化知识长期更新。

Vector

概述

  • Vector是Java Collection Franmework成员。
  • 列队允许添加重复元素
  • 列队允许null的存在
  • 列队从0开始,也就是列队头部的下标是0。
  • 列队支持泛型,这样可以避免ClassCastException异常。

与ArrayList的区别

  • Vector和ArrayList几乎完全项目,几个不相同的特征分别是。
    • Vector是同步的,自带的方法大多被synchronized修饰。所以开销比ArrayList大很多。
    • Vector默认每次扩容大小,ArrayList 是1.5倍;Vector是2倍。
    • 可以指定扩容系数,不指定就是2倍。
  • 相对与ArrayList,Vector牺牲了性能换取同步,但是实际上可以通过Collections.synchronizedList(new ArrayList<>());来返回一个线程安全的List,可以可以使用concurrent包下CopyOnWriteArrayList类。
  • 所以一般不建议使用Vector。

源码分析下Vector

Vector中常量以及变量

1
2
3
4
5
6
7
8
9
10
11
// 集合中的数组元素
protected Object[] elementData;

// 集合中数组大小,这里不是用size。
protected int elementCount;

// 扩容的时候增长数量,如果是0或者负数就是2倍。
protected int capacityIncrement;

// 容器的最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

1、如何创建Vector

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Test
public void test() {
String[] arr = new String[]{"a" , "b" , "c" , "d"};
Vector list = new Vector(1 , 10);
list.addAll(Arrays.asList(arr));
System.out.println(list);

Vector list1 = new Vector(10);
list1.addAll(Arrays.asList(arr));
System.out.println(list1);

Vector list2 = new Vector();
list2.addAll(Arrays.asList(arr));
System.out.println(list2);

Vector list3 = new Vector(Arrays.asList(arr));

System.out.println(list3);
}

输出

1
2
3
4
[a, b, c, d]
[a, b, c, d]
[a, b, c, d]
[a, b, c, d]

这里分别使用了Vectro四个构造方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//list
public Vector(int initialCapacity, int capacityIncrement) {
super();
//指定容器初始化大小和扩容系数。
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
//list1
public Vector(int initialCapacity) {
//指定容器的初始化大小。默认扩容系数0。
this(initialCapacity, 0);
}
//list2
public Vector() {
// 指定容器的初始化大小为10。
this(10);
}
//list2
public Vector(Collection<? extends E> c) {
//将一个Collection容器的元素都复制进来
elementData = c.toArray();
elementCount = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}

1、看下扩容代码

由于Vector的方法和ArrayList的方法太多相似,这里看看如何扩容的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 从add方法入口看
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1); //判断扩容
elementData[elementCount++] = e;
return true;

}

private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
// 如果最小容量不够用了就扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}

private void grow(int minCapacity) {
// overflow-conscious code
// 容器原始大小
int oldCapacity = elementData.length;
// 如果capacityIncrement > 0 新大小 就等于oldCapacity + capacityIncrement 反之就等于 oldCapacity + oldCapacity 相对与2倍了。
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 判断新大小是否超过大限制
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 复制生成新的数组
elementData = Arrays.copyOf(elementData, newCapacity);
}

private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}