Vector Stack源碼解析

Vector可以實(shí)現(xiàn)可增長的對(duì)象數(shù)組拌喉。與數(shù)組一樣派诬,它包含可以使用整數(shù)索引進(jìn)行訪問的組件盟萨。不過吝羞,Vector的大小是可以增加或者減小的兰伤,以便適應(yīng)創(chuàng)建Vector后進(jìn)行添加或者刪除操作。

Vector實(shí)現(xiàn)List接口钧排,繼承AbstractList類敦腔,所以我們可以將其看做隊(duì)列,支持相關(guān)的添加恨溜、刪除符衔、修改找前、遍歷等功能。

/**
    * 構(gòu)造一個(gè)空向量判族,使其內(nèi)部數(shù)據(jù)數(shù)組的大小為 10纸厉,其標(biāo)準(zhǔn)容量增量為零。
    */
    public Vector() {
           this(10);
    }

   /**
    * 構(gòu)造一個(gè)包含指定 collection 中的元素的向量五嫂,這些元素按其 collection 的迭代器返回元素的順序排列。
    */
   public Vector(Collection<? extends E> c) {
       elementData = c.toArray();
       elementCount = elementData.length;
       // c.toArray might (incorrectly) not return Object[] (see 6260652)
       if (elementData.getClass() != Object[].class)
           elementData = Arrays.copyOf(elementData, elementCount,
                   Object[].class);
   }

   /**
    * 使用指定的初始容量和等于零的容量增量構(gòu)造一個(gè)空向量肯尺。
    */
   public Vector(int initialCapacity) {
       this(initialCapacity, 0);
   }

   /**
    *  使用指定的初始容量和容量增量構(gòu)造一個(gè)空的向量沃缘。
    */
   public Vector(int initialCapacity, int capacityIncrement) {
       super();
       if (initialCapacity < 0)
           throw new IllegalArgumentException("Illegal Capacity: "+
                                              initialCapacity);
       this.elementData = new Object[initialCapacity];
       this.capacityIncrement = capacityIncrement;
   }

在成員變量方面,Vector提供了elementData , elementCount则吟, capacityIncrement三個(gè)成員變量槐臀。其中

elementData :”O(jiān)bject[]類型的數(shù)組”,它保存了Vector中的元素氓仲。按照Vector的設(shè)計(jì)elementData為一個(gè)動(dòng)態(tài)數(shù)組水慨,可以隨著元素的增加而動(dòng)態(tài)的增長,其具體的增加方式后面提到(ensureCapacity方法)敬扛。如果在初始化Vector時(shí)沒有指定容器大小晰洒,則使用默認(rèn)大小為10.

elementCount:Vector 對(duì)象中的有效組件數(shù)。

capacityIncrement:向量的大小大于其容量時(shí)啥箭,容量自動(dòng)增加的量谍珊。如果在創(chuàng)建Vector時(shí),指定了capacityIncrement的大屑苯摹砌滞;則,每次當(dāng)Vector中動(dòng)態(tài)數(shù)組容量增加時(shí)>坏怪,增加的大小都是capacityIncrement贝润。如果容量的增量小于等于零,則每次需要增大容量時(shí)铝宵,向量的容量將增大一倍打掘。

同時(shí)Vector是線程安全的!

add(E e)

將指定元素添加到此向量的末尾鹏秋。

public synchronized boolean add(E e) {
       modCount++;     
       ensureCapacityHelper(elementCount + 1);    //確認(rèn)容器大小胧卤,如果操作容量則擴(kuò)容操作
       elementData[elementCount++] = e;   //將e元素添加至末尾
       return true;
   }

這個(gè)方法相對(duì)而言比較簡單,具體過程就是先確認(rèn)容器的大小拼岳,看是否需要進(jìn)行擴(kuò)容操作枝誊,然后將E元素添加到此向量的末尾。

private void ensureCapacityHelper(int minCapacity) {
       //如果
       if (minCapacity - elementData.length > 0)
           grow(minCapacity);
   }

   /**
    * 進(jìn)行擴(kuò)容操作
    * 如果此向量的當(dāng)前容量小于minCapacity惜纸,則通過將其內(nèi)部數(shù)組替換為一個(gè)較大的數(shù)組倆增加其容量叶撒。
    * 新數(shù)據(jù)數(shù)組的大小姜維原來的大小 + capacityIncrement绝骚,
    * 除非 capacityIncrement 的值小于等于零,在后一種情況下祠够,新的容量將為原來容量的兩倍压汪,不過,如果此大小仍然小于 minCapacity古瓤,則新容量將為 minCapacity止剖。
    */
   private void grow(int minCapacity) {
       int oldCapacity = elementData.length;     //當(dāng)前容器大小
       /*
        * 新容器大小
        * 若容量增量系數(shù)(capacityIncrement) > 0,則將容器大小增加到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);
   }

   /**
    * 判斷是否超出最大范圍
    * MAX_ARRAY_SIZE:private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    */
   private static int hugeCapacity(int minCapacity) {
       if (minCapacity < 0)
           throw new OutOfMemoryError();
       return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
   }

對(duì)于Vector整個(gè)的擴(kuò)容過程落君,就是根據(jù)capacityIncrement確認(rèn)擴(kuò)容大小的穿香,若capacityIncrement <= 0 則擴(kuò)大一倍,否則擴(kuò)大至capacityIncrement 绎速。當(dāng)然這個(gè)容量的最大范圍為Integer.MAX_VALUE即皮获,2^32 – 1,所以Vector并不是可以無限擴(kuò)充的纹冤。

remove(Object o)

/**
    * 從Vector容器中移除指定元素E
    */
   public boolean remove(Object o) {
       return removeElement(o);
   }

   public synchronized boolean removeElement(Object obj) {
       modCount++;
       int i = indexOf(obj);   //計(jì)算obj在Vector容器中位置
       if (i >= 0) {
           removeElementAt(i);   //移除
           return true;
       }
       return false;
   }

   public synchronized void removeElementAt(int index) {
       modCount++;     //修改次數(shù)+1
       if (index >= elementCount) {   //刪除位置大于容器有效大小
           throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
       }
       else if (index < 0) {    //位置小于 < 0
           throw new ArrayIndexOutOfBoundsException(index);
       }
       int j = elementCount - index - 1;
       if (j > 0) {   
           //從指定源數(shù)組中復(fù)制一個(gè)數(shù)組洒宝,復(fù)制從指定的位置開始,到目標(biāo)數(shù)組的指定位置結(jié)束萌京。
           //也就是數(shù)組元素從j位置往前移
           System.arraycopy(elementData, index + 1, elementData, index, j);
       }
       elementCount--;   //容器中有效組件個(gè)數(shù) - 1
       elementData[elementCount] = null;    //將向量的末尾位置設(shè)置為null
   }

因?yàn)閂ector底層是使用數(shù)組實(shí)現(xiàn)的雁歌,所以它的操作都是對(duì)數(shù)組進(jìn)行操作,只不過其是可以隨著元素的增加而動(dòng)態(tài)的改變?nèi)萘看笮≈校鋵?shí)現(xiàn)方法是是使用Arrays.copyOf方法將舊數(shù)據(jù)拷貝到一個(gè)新的大容量數(shù)組中将宪。Vector的整個(gè)內(nèi)部實(shí)現(xiàn)都比較簡單,這里就不在重述了橡庞。

Vector遍歷

Vector支持4種遍歷方式较坛。

因?yàn)閂ector實(shí)現(xiàn)了RandmoAccess接口,可以通過下標(biāo)來進(jìn)行隨機(jī)訪問扒最。

for(int i = 0 ; i < vec.size() ; i++){
       value = vec.get(i);
   }

迭代器

Iterator it = vec.iterator();
   while(it.hasNext()){
       value = it.next();
       //do something
   }

for循環(huán)(語法糖 本質(zhì)上也是迭代器)

for(Integer value:vec){
       //do something
   }

Enumeration循環(huán)

Vector vec = new Vector<>();
   Enumeration enu = vec.elements();
   while (enu.hasMoreElements()) {
       value = (Integer)enu.nextElement();
   }

Stack

在Java中Stack類表示后進(jìn)先出(LIFO)的對(duì)象堆棧丑勤。棧是一種非常常見的數(shù)據(jù)結(jié)構(gòu),它采用典型的先進(jìn)后出的操作方式完成的吧趣。每一個(gè)棧都包含一個(gè)棧頂法竞,每次出棧是將棧頂?shù)臄?shù)據(jù)取出,如下:


image.png

Stack通過五個(gè)操作對(duì)Vector進(jìn)行擴(kuò)展强挫,允許將向量視為堆棧岔霸。這個(gè)五個(gè)操作如下:

image.png

Stack繼承Vector,他對(duì)Vector進(jìn)行了簡單的擴(kuò)展:

 public class Stack<E> extends Vector<E>

Stack的實(shí)現(xiàn)非常簡單俯渤,僅有一個(gè)構(gòu)造方法呆细,五個(gè)實(shí)現(xiàn)方法(從Vector繼承而來的方法不算與其中),同時(shí)其實(shí)現(xiàn)的源碼非常簡單

/**
     * 構(gòu)造函數(shù)
     */
    public Stack() {
    }

    /**
     *  push函數(shù):將元素存入棧頂
     */
    public E push(E item) {
        // 將元素存入棧頂八匠。
        // addElement()的實(shí)現(xiàn)在Vector.java中
        addElement(item);

        return item;
    }

    /**
     * pop函數(shù):返回棧頂元素絮爷,并將其從棧中刪除
     */
    public synchronized E pop() {
        E    obj;
        int    len = size();

        obj = peek();
        // 刪除棧頂元素趴酣,removeElementAt()的實(shí)現(xiàn)在Vector.java中
        removeElementAt(len - 1);

        return obj;
    }

    /**
     * peek函數(shù):返回棧頂元素,不執(zhí)行刪除操作
     */
    public synchronized E peek() {
        int    len = size();

        if (len == 0)
            throw new EmptyStackException();
        // 返回棧頂元素坑夯,elementAt()具體實(shí)現(xiàn)在Vector.java中
        return elementAt(len - 1);
    }

    /**
     * 棧是否為空
     */
    public boolean empty() {
        return size() == 0;
    }

    /**
     *  查找“元素o”在棧中的位置:由棧底向棧頂方向數(shù)
     */
    public synchronized int search(Object o) {
        // 獲取元素索引岖寞,elementAt()具體實(shí)現(xiàn)在Vector.java中
        int i = lastIndexOf(o);

        if (i >= 0) {
            return size() - i;
        }
        return -1;
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市柜蜈,隨后出現(xiàn)的幾起案子仗谆,更是在濱河造成了極大的恐慌,老刑警劉巖淑履,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件隶垮,死亡現(xiàn)場離奇詭異,居然都是意外死亡鳖谈,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門阔涉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缆娃,“玉大人,你說我怎么就攤上這事瑰排」嵋” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵椭住,是天一觀的道長崇渗。 經(jīng)常有香客問我,道長京郑,這世上最難降的妖魔是什么宅广? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮些举,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己士鸥,他們只是感情好呻征,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著叼丑,像睡著了一般关翎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鸠信,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天纵寝,我揣著相機(jī)與錄音,去河邊找鬼星立。 笑死店雅,一個(gè)胖子當(dāng)著我的面吹牛政基,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播闹啦,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼沮明,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了窍奋?” 一聲冷哼從身側(cè)響起荐健,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎琳袄,沒想到半個(gè)月后江场,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡窖逗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年址否,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碎紊。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡佑附,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出仗考,到底是詐尸還是另有隱情音同,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布秃嗜,位于F島的核電站权均,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏锅锨。R本人自食惡果不足惜叽赊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望必搞。 院中可真熱鬧蛇尚,春花似錦、人聲如沸顾画。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽研侣。三九已至谱邪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間庶诡,已是汗流浹背惦银。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人扯俱。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓书蚪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親迅栅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子殊校,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容