jdk版本:1.8.0_77
參考文檔:jdk 1.8 docs
Vector類圖
Vector繼承關(guān)系
Vector特點(diǎn)
- Vector對(duì)象內(nèi)部維護(hù)一個(gè)數(shù)組對(duì)象薪丁,可以通過整數(shù)索引訪問數(shù)組元素。
protected Object[] elementData;//存儲(chǔ)對(duì)象的數(shù)組緩沖區(qū)
protected int elementCount;//Vector存儲(chǔ)的元素個(gè)數(shù)
protected int capacityIncrement;//當(dāng)Vector容量不夠擴(kuò)容大小
- Vector通過設(shè)置capacity、capacityIncrement參數(shù)來優(yōu)化存儲(chǔ)管理钮莲;capacity等于數(shù)組長度葡公,當(dāng)Vector數(shù)組不夠用時(shí)擴(kuò)容,擴(kuò)容大小默認(rèn)是capacityIncrement(如果該參數(shù)為0則當(dāng)前數(shù)組長度*2處理)莫秆。
@Test
public void testCapacity() {
//Vector擴(kuò)容是在內(nèi)部數(shù)組放滿之后調(diào)用grow
//擴(kuò)容方式分2種:1.數(shù)組容量*2處理;2.數(shù)組容量變?yōu)閚ewCapacity=oldCapacity+capacityIncrement
Vector v1 = new Vector(1);
Vector v2 = new Vector(1, 1);//如果設(shè)置capacityIncrement則按照第二種方式擴(kuò)容
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());
}
運(yùn)行結(jié)果:
v1 capacity:1|v2 capacity:1
v1 capacity:2|v2 capacity:2
v1 capacity:4|v2 capacity:3
v1间雀、v2初始容量capacity均為1,v2設(shè)置capacityIncrement為1镊屎;v1每次擴(kuò)容為原來容量1倍惹挟,v2每次擴(kuò)容capacityIncrement大小。
private void grow(int minCapacity) {//擴(kuò)容方法源代碼
// overflow-conscious code
int oldCapacity = elementData.length;
//根據(jù)capacityIncrement是否存在選擇擴(kuò)容方式
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數(shù)組容量可以?自動(dòng)擴(kuò)容和手動(dòng)縮容以便適應(yīng)Vector創(chuàng)建之后?數(shù)組大小變化。
@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());
}
運(yùn)行結(jié)果:
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集合迭代時(shí)集合中添加或刪除元素(數(shù)組結(jié)構(gòu)改變了)榴徐,Vector迭代器迭代會(huì)fail-fast(快速失敗)财剖,迭代方法拋出ConcurrentModificationException異常。
@Test
public void testFailFast() throws InterruptedException {
//fail-fast 當(dāng)遍歷Iterator對(duì)象時(shí)如果此時(shí)對(duì)數(shù)組做增/刪操作,拋出異常
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);
}
}
運(yùn)行結(jié)果:
v1:a
v1 remove one element
java.util.ConcurrentModificationException
當(dāng)正在迭代v1時(shí),我們v1做刪除或添加操作,拋出異常。
final void checkForComodification() {//modCount在每次對(duì)象結(jié)果變化時(shí)+1
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
避免出現(xiàn)該問題方法:
@Test
public void testClone() throws InterruptedException {
//假設(shè)有多個(gè)線程同時(shí)操作一個(gè)Vector對(duì)象,如果此時(shí)需要對(duì)Vector遍歷,需要先clone該對(duì)象,這樣就能避免在迭代時(shí)其他線程操作對(duì)象導(dǎo)致迭代失敗
//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);
}
}
運(yùn)行結(jié)果:
v1:a
v2 remove
v1:b
v1:c
當(dāng)我們要迭代一個(gè)v1時(shí)先調(diào)用clone()方法克隆出v2驳规,對(duì)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關(guān)鍵字來保證線程之間同步。