Vector源碼剖析(看不懂直播寫檢討)

將分析以下內容

  • 字段
  • 構造函數
  • 擴容
  • 插入和刪除導致的數組大幅度移動

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()是怎么插入元素的

  1. 判斷角標越界沒毛病
  2. 判斷容量残炮,前面已經講了韭赘,沒毛病
  3. 調用System.arraycopy()將數組從索引處整個往后挪
  4. 在索引處設置新的值
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;
}

所以這里也就不再介紹了泉瞻,至于查詢和修改脉漏,查詢直接返回數組指定索引的值,修改直接修改指定索引的值袖牙,沒什么說的

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末侧巨,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子鞭达,更是在濱河造成了極大的恐慌司忱,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件畴蹭,死亡現場離奇詭異坦仍,居然都是意外死亡,警方通過查閱死者的電腦和手機叨襟,發(fā)現死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門繁扎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人糊闽,你說我怎么就攤上這事梳玫。” “怎么了右犹?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵提澎,是天一觀的道長。 經常有香客問我傀履,道長虱朵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任钓账,我火速辦了婚禮碴犬,結果婚禮上,老公的妹妹穿的比我還像新娘梆暮。我一直安慰自己服协,他們只是感情好,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布啦粹。 她就那樣靜靜地躺著偿荷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪唠椭。 梳的紋絲不亂的頭發(fā)上跳纳,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音贪嫂,去河邊找鬼寺庄。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的斗塘。 我是一名探鬼主播赢织,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼馍盟!你這毒婦竟也來了于置?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤贞岭,失蹤者是張志新(化名)和其女友劉穎八毯,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體瞄桨,經...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡宪彩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了讲婚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡俊柔,死狀恐怖筹麸,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情雏婶,我是刑警寧澤物赶,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站留晚,受9級特大地震影響酵紫,放射性物質發(fā)生泄漏。R本人自食惡果不足惜错维,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一搅窿、第九天 我趴在偏房一處隱蔽的房頂上張望彩郊。 院中可真熱鬧,春花似錦、人聲如沸借卧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽俯渤。三九已至,卻和暖如春侨嘀,著一層夾襖步出監(jiān)牢的瞬間臭挽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工咬腕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留欢峰,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像赤赊,于是被迫代替她去往敵國和親闯狱。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內容