jdk版本:1.8.0_77
参考文档:jdk 1.8 docs
Vector类图
Vector特点
- Vector对象内部维护一个数组对象,可以通过整数索引访问数组元素。
protected Object[] elementData;//存储对象的数组缓冲区
protected int elementCount;//Vector存储的元素个数
protected int capacityIncrement;//当Vector容量不够扩容大小
- Vector通过设置capacity、capacityIncrement参数来优化存储管理;capacity等于数组长度,当Vector数组不够用时扩容,扩容大小默认是capacityIncrement(如果该参数为0则当前数组长度*2处理)。
@Test
public void testCapacity() {
//Vector扩容是在内部数组放满之后调用grow
//扩容方式分2种:1.数组容量*2处理;2.数组容量变为newCapacity=oldCapacity+capacityIncrement
Vector v1 = new Vector(1);
Vector v2 = new Vector(1, 1);//如果设置capacityIncrement则按照第二种方式扩容
System.out.println("v1 capacity:" + v1.capacity() + "|v2 capacity:" + v2.capacity());
v1.add("1");
v2.add("1");
v1.add("2");
v2.add("2");
System.out.println("v1 capacity:" + v1.capacity() + "|v2 capacity:" + v2.capacity());
v1.add("3");
v2.add("3");
System.out.println("v1 capacity:" + v1.capacity() + "|v2 capacity:" + v2.capacity());
}
运行结果:
v1 capacity:1|v2 capacity:1
v1 capacity:2|v2 capacity:2
v1 capacity:4|v2 capacity:3
v1、v2初始容量capacity均为1,v2设置capacityIncrement为1;v1每次扩容为原来容量1倍,v2每次扩容capacityIncrement大小。
private void grow(int minCapacity) {//扩容方法源代码
// overflow-conscious code
int oldCapacity = elementData.length;
//根据capacityIncrement是否存在选择扩容方式
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);
}
- Vector数组容量可以�自动扩容和手动缩容以便适应Vector创建之后�数组大小变化。
@Test
public void testCapcityIncrementAndReduce() {
Vector v1 = new Vector(0, 10);
System.out.println("v1 capcity:" + v1.capacity());
v1.add("1");
System.out.println("v1 capcity:" + v1.capacity());
v1.trimToSize();
System.out.println("v1 capcity:" + v1.capacity());
}
运行结果:
v1 capcity:0
v1 capcity:10
v1 capcity:1
public synchronized boolean add(E e) {//add方法源代码
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
public synchronized void trimToSize() {//缩容源代码
modCount++;
int oldCapacity = elementData.length;
if (elementCount < oldCapacity) {
elementData = Arrays.copyOf(elementData, elementCount);
}
}
可以通过trimToSize方法减少Vector所占用空间。
- 如果在Vector集合迭代时集合中添加或删除元素(数组结构改变了),Vector迭代器迭代会fail-fast(快速失败),迭代方法抛出ConcurrentModificationException异常。
@Test
public void testFailFast() throws InterruptedException {
//fail-fast 当遍历Iterator对象时如果此时对数组做增/删操作,抛出异常
Vector v1 = new Vector();
v1.add("a");
v1.add("b");
v1.add("c");
Iterator it = v1.iterator();
new Thread(() -> {
try {
Thread.sleep(1000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
v1.remove("c");
System.out.println("v1 remove one element");
}).start();
while (it.hasNext()) {
Object next = it.next();
System.out.println("v1:" + next);
Thread.sleep(3000l);
}
}
运行结果:
v1:a
v1 remove one element
java.util.ConcurrentModificationException
当正在迭代v1时,我们v1做删除或添加操作,抛出异常。
final void checkForComodification() {//modCount在每次对象结果变化时+1
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
避免出现该问题方法:
@Test
public void testClone() throws InterruptedException {
//假设有多个线程同时操作一个Vector对象,如果此时需要对Vector遍历,需要先clone该对象,这样就能避免在迭代时其他线程操作对象导致迭代失败
//Vector是线程安全的
Vector v1 = new Vector();
v1.add("a");
v1.add("b");
v1.add("c");
Vector v2 = (Vector) v1.clone();
Iterator it = v1.iterator();
new Thread(() -> {
try {
Thread.sleep(1000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
v2.remove("c");
System.out.println("v2 remove");
}).start();
while (it.hasNext()) {
Object next = it.next();
System.out.println("v1:" + next);
Thread.sleep(3000l);
}
}
运行结果:
v1:a
v2 remove
v1:b
v1:c
当我们要迭代一个v1时先调用clone()方法克隆出v2,对v2迭代。
public synchronized Object clone() {
try {
@SuppressWarnings("unchecked")
Vector<E> v = (Vector<E>) super.clone();
v.elementData = Arrays.copyOf(elementData, elementCount);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
- Vector是线程安全的;如果不需要线程安全,可以使用ArrayList代替Vector。
public synchronized void addElement(E obj) {}
public synchronized boolean removeElement(Object obj) {}
public synchronized void removeAllElements() {}
...
方法加上synchronized关键字来保证线程之间同步。