Vector笔记整理

Vector

Vector是比较早期的实现,底层同ArrayList一样都是使用了可扩容的数组结构,扩容的方法有稍微的差别。Vector中实现的方法几乎都是synchronized同步方法,虽然是线程安全的但是性能上开销比较大,日常开发中已经很少会使用到了。基本上都被其他更好的选择代替了。这里记录一下,对比与ArrayList

Vector的结构与常量

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
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{

//存放元素的数组
protected Object[] elementData;

//元素的个数
protected int elementCount;

//矢量容量的自动量当其尺寸大于其容量时递增。如果容量增量小于或等于零的矢量在每次需要增长时翻倍。(源码的解释)
protected int capacityIncrement;

//构造函数
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//指定容量的实现方法
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}

public Vector(int initialCapacity) {
this(initialCapacity, 0);
}

//无参的构造函数,默认的数组容量为10个元素
public Vector() {
this(10);
}
...}

扩容机制

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
//ArrayList在需要扩容的时,新数组的容量会变为原来的1.5倍,Vector在不指定增长系数时,通常会增加为原来的两倍。
public synchronized void ensureCapacity(int minCapacity) {
if (minCapacity > 0) {
modCount++;
ensureCapacityHelper(minCapacity);
}
}

private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
//新增元素大于数组的长度,就进行扩容流程
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//当增长矢量没有指定(0)时,扩容后的新数组长度为旧数组的两倍 oldCapacity + oldCapacity
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
//指定增长系数,校验是否符合
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//临界值的处理,同ArrayList大同小异
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;
}

增删改查

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
40
41
42
43
44
45
//增加元素
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}

//删除元素
public synchronized boolean removeElement(Object obj) {
modCount++;
int i = indexOf(obj);
if (i >= 0) {
removeElementAt(i);
return true;
}
return false;
}

public synchronized void removeAllElements() {
modCount++;
// Let gc do its work
for (int i = 0; i < elementCount; i++)
elementData[i] = null;

elementCount = 0;
}

//修改元素
public synchronized E set(int index, E element) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);

E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}

//查询
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);

return elementData(index);
}

总结

1.VectorArrayList实现原理是一样的,底层都使用了扩容数组,默认给的容量为10

2.Vector的一些常用方法都加了锁synchronized,这就导致了不必要的性能开销(不要同步方法的时候强制加锁,有点泛滥)

3.可以指定矢量增加系数capacityIncrement,但是在扩容流程中会进行校验判断是否符合实际要求:

1
2
3
4
5
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
//指定增长系数,校验是否符合
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;

如果未指定capacityIncrement则当需要时会扩容为原来的两倍,在性能造成了不必要的浪费(对比与ArrayList的1.5)。

4.大多数情况下,已经不在使用,如果需要同步操作可以有更好的替代类(concurrent下的集合)。

这个功能是摆设,看看就好~~~