深入學(xué)習(xí)Java之Vector

深入學(xué)習(xí)Java之Vector

前言

在前面我們學(xué)習(xí)了關(guān)于List接口中的幾個(gè)實(shí)現(xiàn)ArrayList智厌、LinkedList以及Queue接口的實(shí)現(xiàn)ProrityQueue、接下來我們來學(xué)習(xí)另外一個(gè)比較常用的List接口的實(shí)現(xiàn)VectorVector屬于元老級別的容器了骆莹,從JDK1.0就已經(jīng)存在了,實(shí)現(xiàn)基本上跟ArrayList是類似的,只不過由于Vector加多了一些同步機(jī)制莺禁,保證Vector是線程安全的(還記得嗎,之前學(xué)過的那幾個(gè)容器都是非線程安全的)

Vector的繼承結(jié)構(gòu)

首先先來看下Vector的繼承結(jié)構(gòu)


Vector繼承結(jié)構(gòu)

從上圖中可以看到窄赋,Vector所繼承或者實(shí)現(xiàn)的類/接口都是之前所接觸過的哟冬,言下之意,除非Vector自身新增了一些方法忆绰,否則浩峡,Vector的操作方式是跟ArrayList的操作是基本相同的,由于我們在前面的內(nèi)容中已經(jīng)學(xué)習(xí)過了上面所涉及到的相關(guān)接口错敢,這里就不再重復(fù)了翰灾,如果還不是很熟悉的話,可以翻閱前面的內(nèi)容進(jìn)行學(xué)習(xí)

Vector源碼剖析

接下來我們來深入學(xué)習(xí)Vector的源碼

Vector的組成

    // 內(nèi)部實(shí)現(xiàn)為Object數(shù)組
    protected Object[] elementData;
    // 實(shí)際元素的數(shù)量
    protected int elementCount;

構(gòu)造方法


    // 指定容量以及指定擴(kuò)容時(shí)的增長量
    public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }

    // 指定初始化容量稚茅,默認(rèn)擴(kuò)容時(shí)的增長量為0
    public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }

    // 空構(gòu)造方法纸淮,默認(rèn)初始化容量為10
    public Vector() {
        this(10);
    }

    // 使用容器進(jìn)行構(gòu)造
    public Vector(Collection<? extends E> c) {
        // 直接將容器轉(zhuǎn)為數(shù)組,并且指向該數(shù)組
        elementData = c.toArray();
        elementCount = elementData.length;
        // 如果容器中元素的類型不是Object亚享,則進(jìn)行轉(zhuǎn)換
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
    }

插入元素


    // 需要注意的是咽块,這里的操作使用了synchronized修飾
    public synchronized boolean add(E e) {
        modCount++;
        // 確保容量
        ensureCapacityHelper(elementCount + 1);
        // 默認(rèn)插入在最后面
        elementData[elementCount++] = e;
        return true;
    }

    // 默認(rèn)在最后插入元素
    public synchronized void addElement(E obj) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = obj;
    }

    // 在指定位置插入元素
    public synchronized void insertElementAt(E obj, int index) {
        modCount++;
        if (index > elementCount) {
            throw new ArrayIndexOutOfBoundsException(index
                                                     + " > " + elementCount);
        }
        ensureCapacityHelper(elementCount + 1);
        // 將數(shù)組中index后面的內(nèi)容后移
        System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
        elementData[index] = obj;
        elementCount++;
    }

    // 在指定位置插入元素,這里可以看到欺税,底層是使用insertElementAt方法
    public void add(int index, E element) {
        insertElementAt(element, index);
    }

    // 將容器的內(nèi)容插入到Vector中侈沪,默認(rèn)是插入在后面
    public synchronized boolean addAll(Collection<? extends E> c) {
        modCount++;
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityHelper(elementCount + numNew);
        // 直接將a的內(nèi)容拷貝到elementData后面
        System.arraycopy(a, 0, elementData, elementCount, numNew);
        elementCount += numNew;
        return numNew != 0;
    }

    // 在指定位置加入容器中的所有元素
    public synchronized boolean addAll(int index, Collection<? extends E> c) {
        modCount++;
        if (index < 0 || index > elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityHelper(elementCount + numNew);

        int numMoved = elementCount - index;

        // 如果需要移動(dòng)的元素大于0,也就是
        // 插入的位置不是在當(dāng)前Vector的最后面晚凿,則將index之后的
        // 元素先后移
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);
        // 將新的元素拷貝至當(dāng)前數(shù)組
        System.arraycopy(a, 0, elementData, index, numNew);
        elementCount += numNew;
        return numNew != 0;
    }

確保容量以及動(dòng)態(tài)增長


    // 確保容量
    private void ensureCapacityHelper(int minCapacity) {
        // 如果所需要的最小容量大于當(dāng)前數(shù)組的長度亭罪,則進(jìn)行擴(kuò)容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    // 動(dòng)態(tài)增長
    private void grow(int minCapacity) {

        int oldCapacity = elementData.length;
        // 如果構(gòu)造Vector的時(shí)候,有傳入增長的數(shù)量歼秽,則使用該數(shù)組
        // 否則应役,默認(rèn)的增長為原來容量的一倍
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        // 如果增長之后發(fā)現(xiàn)小于所需要的最小容量
        // 則使用所需的最小容量
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        // 如果新的容量大于允許的最大值,則不使用該值
        // 直接進(jìn)行所需要的最小容量確認(rèn)燥筷,注意扛吞,此時(shí)的最小容量是比較大
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // 將舊的數(shù)組中的元素拷貝至新的數(shù)組中
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    // 最大容量確定
    private static int hugeCapacity(int minCapacity) {
        // 如果此時(shí)的容量小于0,說明出現(xiàn)了溢出荆责,從上面的內(nèi)容可以
        // 知道滥比,minCapacity = elementCount + 新加入的數(shù)據(jù)的長度
        // 此時(shí)有可能會(huì)導(dǎo)致整數(shù)溢出,所以需要進(jìn)行特殊判斷
        if (minCapacity < 0) 
            throw new OutOfMemoryError();
        // 如果所申請的內(nèi)存大于允許的最大值做院,則使用Integer.MAX_VALUE
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

獲取元素


    // 獲取第一個(gè)元素
    public synchronized E firstElement() {
        if (elementCount == 0) {
            throw new NoSuchElementException();
        }
        return elementData(0);
    }

    // 獲取最后一個(gè)元素
    public synchronized E lastElement() {
        if (elementCount == 0) {
            throw new NoSuchElementException();
        }
        return elementData(elementCount - 1);
    }

    // 指定位置的元素
    public synchronized E elementAt(int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
        }

        return elementData(index);
    }

    // 獲取指定位置的元素
    public synchronized E get(int index) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        return elementData(index);
    }

    // 返回元素盲泛,這里直接將Object類型轉(zhuǎn)化為泛型所指定的類型
    E elementData(int index) {
        return (E) elementData[index];
    }

獲取元素的索引

    
    // 查找指定元素的索引
    public int indexOf(Object o) {
        return indexOf(o, 0);
    }

    // 從指定位置開始濒持,查找指定元素的索引
    public synchronized int indexOf(Object o, int index) {
        // 如果元素是null,則返回第一個(gè)null元素的索引
        if (o == null) {
            for (int i = index ; i < elementCount ; i++)
                if (elementData[i]==null)
                    return i;
        // 否則寺滚,返回第一個(gè)匹配的元素的索引
        } else {
            for (int i = index ; i < elementCount ; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        // 如果找不到柑营,則返回-1
        return -1;
    }

    // 從后往前查找第一個(gè)匹配元素的索引
    public synchronized int lastIndexOf(Object o) {
        return lastIndexOf(o, elementCount-1);
    }

    // 從指定位置查找,從后往前第一個(gè)匹配的元素的索引
    public synchronized int lastIndexOf(Object o, int index) {
        if (index >= elementCount)
            throw new IndexOutOfBoundsException(index + " >= "+ elementCount);
        // 同上
        if (o == null) {
            for (int i = index; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = index; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

修改元素


    // 將指定位置的元素的值設(shè)置為新的值
    public synchronized void setElementAt(E obj, int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                     elementCount);
        }
        elementData[index] = obj;
    }

    // 替換指定位置的元素值村视,并且返回舊值
    public synchronized E set(int index, E element) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

刪除元素


    // 刪除指定位置的元素
    public synchronized E remove(int index) {
        modCount++;
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);
        E oldValue = elementData(index);

        int numMoved = elementCount - index - 1;
        // 如果需要移動(dòng)的元素?cái)?shù)量大于0官套,也就是刪除的元素不是最后一個(gè)元素
        // 則將后面的元素前移
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        // 將最后面的元素(此時(shí)所有的元素已經(jīng)前移了一個(gè)位置)指向null
        // 輔助垃圾回收機(jī)制進(jìn)行垃圾回收
        elementData[--elementCount] = null;

        return oldValue;
    }

    // 刪除第一個(gè)匹配的元素
    public boolean remove(Object o) {
        return removeElement(o);
    }

    // 刪除指定元素
    public synchronized boolean removeElement(Object obj) {
        modCount++;
        // 查找第一個(gè)找到的元素
        int i = indexOf(obj);
        if (i >= 0) {
            removeElementAt(i);
            return true;
        }
        return false;
    }

    // 刪除指定位置的元素
    public synchronized void removeElementAt(int index) {
        modCount++;
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                     elementCount);
        }
        else if (index < 0) {
            throw new ArrayIndexOutOfBoundsException(index);
        }
        int j = elementCount - index - 1;
        if (j > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, j);
        }
        elementCount--;
        elementData[elementCount] = null; /* to let gc do its work */
    }

    // 刪除指定范圍的元素
    protected synchronized void removeRange(int fromIndex, int toIndex) {
        modCount++;
        int numMoved = elementCount - toIndex;
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);

        // Let gc do its work
        int newElementCount = elementCount - (toIndex-fromIndex);
        while (elementCount != newElementCount)
            elementData[--elementCount] = null;
    }

    // 刪除所有元素
    public synchronized void removeAllElements() {
        modCount++;
        // 所有元素指向null,方便垃圾回收器進(jìn)行垃圾回收
        for (int i = 0; i < elementCount; i++)
            elementData[i] = null;

        elementCount = 0;
    }

    // 刪除容量中包含的元素
    public synchronized boolean removeAll(Collection<?> c) {
        return super.removeAll(c);
    }

    // 刪除不包含在容器中的元素
    public synchronized boolean retainAll(Collection<?> c) {
        return super.retainAll(c);
    }

    // 清除容器中的元素
    public void clear() {
        removeAllElements();
    }

其他常用操作


    // 查看是否包含容器中的所有元素
    public synchronized boolean containsAll(Collection<?> c) {
        return super.containsAll(c);
    }

    // 將Vector轉(zhuǎn)成array
    public synchronized Object[] toArray() {
        return Arrays.copyOf(elementData, elementCount);
    }

    // 將Vector轉(zhuǎn)成array
    public synchronized <T> T[] toArray(T[] a) {
        if (a.length < elementCount)
            return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());

        System.arraycopy(elementData, 0, a, 0, elementCount);

        if (a.length > elementCount)
            a[elementCount] = null;

        return a;
    }

    // 查看是否包含某個(gè)元素
    public boolean contains(Object o) {
        return indexOf(o, 0) >= 0;
    }

    // 返回枚舉對象
    public Enumeration<E> elements() {
        return new Enumeration<E>() {
            int count = 0;

            public boolean hasMoreElements() {
                return count < elementCount;
            }

            public E nextElement() {
                synchronized (Vector.this) {
                    if (count < elementCount) {
                        return elementData(count++);
                    }
                }
                throw new NoSuchElementException("Vector Enumeration");
            }
        };
    }

    // 判斷是否為空
    public synchronized boolean isEmpty() {
        return elementCount == 0;
    }

    // 查看元素個(gè)數(shù)
    public synchronized int size() {
        return elementCount;
    }

    // 查看容量
    public synchronized int capacity() {
        return elementData.length;
    }

    // 手動(dòng)調(diào)整數(shù)組的大小蚁孔,如果指定的容量比當(dāng)前容量小
    // 會(huì)刪除后面的元素
    public synchronized void setSize(int newSize) {
        modCount++;
        if (newSize > elementCount) {
            ensureCapacityHelper(newSize);
        } else {
            for (int i = newSize ; i < elementCount ; i++) {
                elementData[i] = null;
            }
        }
        elementCount = newSize;
    }

    // 將容量縮減為元素個(gè)數(shù)大小
    public synchronized void trimToSize() {
        modCount++;
        int oldCapacity = elementData.length;
        if (elementCount < oldCapacity) {
            elementData = Arrays.copyOf(elementData, elementCount);
        }
    }

    // 將數(shù)組的元素拷貝至指定的數(shù)組中
    public synchronized void copyInto(Object[] anArray) {
        System.arraycopy(elementData, 0, anArray, 0, elementCount);
    }

總結(jié)

本小節(jié)主要學(xué)習(xí)了Vector奶赔,從上面的代碼分析中可以看到,Vector的基本操作和實(shí)現(xiàn)都是與ArrayList類似的杠氢,不過ArrayList是非線程安全的站刑,而Vector是線程安全的,言下之意鼻百,當(dāng)在多線程環(huán)境下使用List容器時(shí)绞旅,Vector是比較好的選擇,不過温艇,由于進(jìn)行同步等的操作因悲,Vector的效率理論上會(huì)比其他幾個(gè)List的操作低一些,而在非多線程的環(huán)境下勺爱,則可以根據(jù)需要選擇ArrayList或者LinkedList囤捻,以便達(dá)到更高的效率

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市邻寿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌视哑,老刑警劉巖绣否,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異挡毅,居然都是意外死亡蒜撮,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門跪呈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來段磨,“玉大人,你說我怎么就攤上這事耗绿∑恢В” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵误阻,是天一觀的道長债蜜。 經(jīng)常有香客問我晴埂,道長,這世上最難降的妖魔是什么寻定? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任儒洛,我火速辦了婚禮,結(jié)果婚禮上狼速,老公的妹妹穿的比我還像新娘琅锻。我一直安慰自己,他們只是感情好向胡,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布恼蓬。 她就那樣靜靜地躺著,像睡著了一般捷枯。 火紅的嫁衣襯著肌膚如雪滚秩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天淮捆,我揣著相機(jī)與錄音郁油,去河邊找鬼。 笑死攀痊,一個(gè)胖子當(dāng)著我的面吹牛桐腌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播苟径,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼案站,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了棘街?” 一聲冷哼從身側(cè)響起蟆盐,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎遭殉,沒想到半個(gè)月后石挂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡险污,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年痹愚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛔糯。...
    茶點(diǎn)故事閱讀 38,716評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拯腮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蚁飒,到底是詐尸還是另有隱情动壤,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布淮逻,位于F島的核電站狼电,受9級特大地震影響蜒灰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜肩碟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一强窖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧削祈,春花似錦翅溺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吨拍,卻和暖如春褪猛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背羹饰。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工伊滋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人队秩。 一個(gè)月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓笑旺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親馍资。 傳聞我的和親對象是個(gè)殘疾皇子筒主,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評論 2 350

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法鸟蟹,內(nèi)部類的語法乌妙,繼承相關(guān)的語法,異常的語法建钥,線程的語...
    子非魚_t_閱讀 31,599評論 18 399
  • 從三月份找實(shí)習(xí)到現(xiàn)在藤韵,面了一些公司,掛了不少锦针,但最終還是拿到小米、百度置蜀、阿里勋乾、京東杭跪、新浪、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,218評論 11 349
  • Java源碼研究之容器(1) 如何看源碼 很多時(shí)候我們看源碼, 看完了以后經(jīng)常也沒啥收獲, 有些地方看得懂, 有些...
    駱駝騎士閱讀 989評論 0 22
  • 張OO閱讀 121評論 0 0
  • 犬犬我是一名將要畢業(yè)的大五預(yù)防醫(yī)學(xué)生莺葫,讀這個(gè)專業(yè)的人都知道,這個(gè)專業(yè)遠(yuǎn)沒有就業(yè)指南上的那么容易找到工作拖刃。要么拿著研...
    翻滾的潘潘閱讀 193評論 0 0