將分析以下內容
- 字段
- 構造函數
- 擴容
- 插入和刪除導致的數組大幅度移動
1.首先來看一下Vector里面的屬性
這個就是用來存儲元素的數組
protected Object[] elementData;
這個是數組已使用的長度
protected int elementCount;
這個是每次擴容時增加的長度塞茅,不同于ArrayList举塔,Vector可以在初始化時指定每次擴容時的長度
protected int capacityIncrement;
2.接下來看一下Vector里面的構造函數
這個參數時無參的继控,它會默認給我們一個初始容量為10,可以看到還需要調用另一個構造函數
public Vector() {
this(10);
}
這個構造函數給了我們默認的擴容長度增長值,可以看到還需要調用另一個構造函數
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
這個函數指定了初始容量和擴容增長長度师坎,完成對各屬性的初始化
public Vector(int initialCapacity, int capacityIncrement) {
super();
//初始容量<0直接拋異常
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//初始化數組以及容量增長
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
3.接下來看一下Vector的增刪
Vector在線程不安全的地方使用了synchronized修飾,因此Vector是線程安全的
public synchronized boolean add(E e) {
modCount++;//數組修改的次數,該變量在AbstractList定義堪滨,不研究
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
在添加元素前胯陋,需要調用ensureCapacityHelper()方法,并傳遞了當前已使用數組長度+1作為最小申請容量
該方法用于判斷是否執(zhí)行擴容袱箱,判斷條件就是最小申請容量是否大于數組總長度
private void ensureCapacityHelper(int minCapacity) {
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
grow()方法時執(zhí)行擴容的具體邏輯
1.計算新容量
- 如果指定了每次擴容增長長度遏乔,新容量=舊容量+每次擴容增長長度
- 如果沒有指定,新容量=2 * 舊容量
2.判斷新容量大小是否小于最小申請容量(當你需要添加多個元素发笔,而你的每次擴容增長長度又設置的太忻巳)
3.新容量大于最大申請容量時,使用Integer.MAX_VALUE(這里直接看一下了讨,一般不會這么大)
//數組分配的最大容量捻激,沒人的數組想要這么大的吧,很占內存的
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) {
//1.計算新容量
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
//2.判斷新容量大小是否小于最小申請容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//新容量大于最大申請容量時量蕊,使用Integer.MAX_VALUE
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
下面我們來用代碼測試一下
public class Test {
public static void main(String[] args) {
Vector<String> vector = new Vector<String>(1, 2);
System.out.println("初始容量:" + vector.capacity());
vector.add("1");
System.out.println("添加1個元素后的容量:" + vector.capacity());
vector.add("2");
System.out.println("添加2個元素后的容量:" + vector.capacity());
vector.add("3");
vector.add("4");
System.out.println("添加4個元素后的容量:" + vector.capacity());
}
}
在這里插入圖片描述
這里我們了解了Vector是如何進行擴容的铺罢,接下來我們看一看Vector如何進行插入
public void add(int index, E element) {
insertElementAt(element, index);
}
傳遞了元素和索引,我們來看看insertElementAt()是怎么插入元素的
- 判斷角標越界沒毛病
- 判斷容量残炮,前面已經講了韭赘,沒毛病
- 調用System.arraycopy()將數組從索引處整個往后挪
- 在索引處設置新的值
public synchronized void insertElementAt(E obj, int index) {
modCount++; //數組修改的次數,該變量在AbstractList定義,不研究
if (index > elementCount) {
throw new ArrayIndexOutOfBoundsException(index
+ " > " + elementCount);
}
ensureCapacityHelper(elementCount + 1);
System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
elementData[index] = obj;
elementCount++;
}
下面是System.arraycopy()方法的圖解
在這里插入圖片描述
下面我們來看看Vector如何進行刪除
看到下面是不是絕對和插入非常相似
public synchronized E remove(int index) {
modCount++;//數組修改的次數,該變量在AbstractList定義势就,不研究
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
int numMoved = elementCount - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--elementCount] = null; // Let gc do its work
return oldValue;
}
所以這里也就不再介紹了泉瞻,至于查詢和修改脉漏,查詢直接返回數組指定索引的值,修改直接修改指定索引的值袖牙,沒什么說的