天天看点

Java集合类框架源码分析 之 Vector源码解析 【8】

按照国际惯例,还是先来看下类简介,有助于从整体上对Vecotr有一个大致的了解:

/**
 * Vector 实现了一个增长的数组对象,像数组一样,通过索引可以访问元素组件。
 * 然而,和数组一旦创建后,长度就保持不变的特性来说,在 Vector 创建之后,可以通过add/remove实现数组长度的放缩。
 * The {@code Vector} class implements a growable array of
 * objects. Like an array, it contains components that can be
 * accessed using an integer index. However, the size of a
 * {@code Vector} can grow or shrink as needed to accommodate
 * adding and removing items after the {@code Vector} has been created.
 *
 * 每个vector都试图通过维护 capacity{容量}和 capacityIncrement{容量增量}来优化存储管理。capacity{容量}至少要和vector大小一样大;
 * 它通常更大,因为当组件添加到vector时,vector的存储以块的形式增加,大小为capacityIncrement{容量增量}。
 * 应用程序可以在插入大量组件之前增加向量的容量,这减少了增量重新分配的次数。
 * <p>Each vector tries to optimize storage management by maintaining a
 * {@code capacity} and a {@code capacityIncrement}. The
 * {@code capacity} is always at least as large as the vector
 * size; it is usually larger because as components are added to the
 * vector, the vector's storage increases in chunks the size of
 * {@code capacityIncrement}. An application can increase the
 * capacity of a vector before inserting a large number of
 * components; this reduces the amount of incremental reallocation.
 *
 * 作为 List 接口的前身,Vector 从一开始就秉持迭代器 iterator 快速失败的特性。
 * <p><a name="fail-fast">
 * The iterators returned by this class's {@link #iterator() iterator} and
 * {@link #listIterator(int) listIterator} methods are <em>fail-fast</em></a>:
 * if the vector is structurally modified at any time after the iterator is
 * created, in any way except through the iterator's own
 * {@link ListIterator#remove() remove} or
 * {@link ListIterator#add(Object) add} methods, the iterator will throw a
 * {@link ConcurrentModificationException}.  Thus, in the face of
 * concurrent modification, the iterator fails quickly and cleanly, rather
 * than risking arbitrary, non-deterministic behavior at an undetermined
 * time in the future.  The {@link Enumeration Enumerations} returned by
 * the {@link #elements() elements} method are <em>not</em> fail-fast.
 *
 * 快速失败的特性只能用来调试代码,不能依赖该特性,来保证代码质量。
 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
 * as it is, generally speaking, impossible to make any hard guarantees in the
 * presence of unsynchronized concurrent modification.  Fail-fast iterators
 * throw {@code ConcurrentModificationException} on a best-effort basis.
 * Therefore, it would be wrong to write a program that depended on this
 * exception for its correctness:  <i>the fail-fast behavior of iterators
 * should be used only to detect bugs.</i>
 *
 * 从 v1.2 开始,这个类被List接口实现来覆盖替代,同为 接口 Java Collection 框架的成员之一,不像新的接口实现,Vector是线程安全的。
 * 如果不需要线程安全,建议使用ArrayList来替换Vector.
 * <p>As of the Java 2 platform v1.2, this class was retrofitted to
 * implement the {@link List} interface, making it a member of the
 * <a href="{@docRoot}/../technotes/guides/collections/index.html" target="_blank" rel="external nofollow" >
 * Java Collections Framework</a>.  Unlike the new collection
 * implementations, {@code Vector} is synchronized.  If a thread-safe
 * implementation is not needed, it is recommended to use {@link
 * ArrayList} in place of {@code Vector}.
 *
 * @author  Lee Boynton
 * @author  Jonathan Payne
 * @see Collection
 * @see LinkedList
 * @since   JDK1.0
 */
           

从类简介中,可以看出,虽然Vector出道的早,但没有自成一派,更没有发展壮大,仍然被纳入了后来者居上的List的接口,这就说明了投资有风险,创业需谨慎,谁都想享受第一个吃螃蟹所带来的红利,但是也要注意背后所酝酿的风险。市场先行者,一般会为旁窥者提供第一手的素材,哪有坑,哪有利,付出的是自己,但是别人却是无本万利,性价比最高,利益最大化。

探索者,有风险,成则传奇,败则被遗忘,试问各位,现在,还有谁在用Vector呢?

用于尝试的人,他们可能会失败,但是对于这样的人,我们要学会敬重,因为,他们虽有不足,但是却从无到有,披荆斩棘的走出了一条路,为后来者指明了方向,为继往开来的人最大化的规避了风险。

他们虽败犹荣,虽早已不在江湖,但江湖永远都会有他的传说。

这样的大哥,值得我们花点精力来详细的进行研究和认识,来看下Vector的方法:

public synchronized boolean add(Object arg0){}
public void add(int arg0,Object arg1){}
public synchronized Object remove(int arg0){}
public boolean remove(Object arg0){}
public synchronized Object get(int arg0){}
public synchronized boolean equals(Object arg0){}
public synchronized String toString(){}
public synchronized int hashCode(){}
public synchronized Object clone(){}
public int indexOf(Object arg0){}
public synchronized int indexOf(Object arg0,int arg1){}
public void clear(){}
public synchronized boolean isEmpty(){}
public synchronized int lastIndexOf(Object arg0,int arg1){}
public synchronized int lastIndexOf(Object arg0){}
public boolean contains(Object arg0){}
public synchronized void replaceAll(UnaryOperator arg0){}
public Enumeration elements(){}
public synchronized int size(){}
public synchronized List subList(int arg0,int arg1){}
public synchronized Object[] toArray(){}
public synchronized Object[] toArray(Object[] arg0){}
public synchronized Iterator iterator(){}
public Spliterator spliterator(){}
public synchronized boolean addAll(int arg0,Collection arg1){}
public synchronized boolean addAll(Collection arg0){}
public synchronized void addElement(Object arg0){}
public synchronized Object elementAt(int arg0){}
public synchronized void forEach(Consumer arg0){}
public synchronized Object set(int arg0,Object arg1){}
public synchronized int capacity(){}
public synchronized void ensureCapacity(int arg0){}
public synchronized void trimToSize(){}
public synchronized void copyInto(Object[] arg0){}
public synchronized void setSize(int arg0){}
public synchronized Object firstElement(){}
public synchronized Object lastElement(){}
public synchronized void setElementAt(Object arg0,int arg1){}
public synchronized void removeElementAt(int arg0){}
public synchronized void insertElementAt(Object arg0,int arg1){}
public synchronized boolean removeElement(Object arg0){}
public synchronized void removeAllElements(){}
public synchronized boolean containsAll(Collection arg0){}
public synchronized boolean removeAll(Collection arg0){}
public synchronized boolean retainAll(Collection arg0){}
public synchronized ListIterator listIterator(){}
public synchronized ListIterator listIterator(int arg0){}
public synchronized boolean removeIf(Predicate arg0){}
public synchronized void sort(Comparator arg0){}
public final void wait(long arg0,int arg1) throws InterruptedException{}
public final native void wait(long arg0) throws InterruptedException{}
public final void wait() throws InterruptedException{}
public final native Class getClass(){}
public final native void notify(){}
public final native void notifyAll(){}
public Stream stream(){}
public Stream parallelStream(){}
           

看出来特点没有,很明显,方法上一水的带了synchronized关键字来进行修饰,这也是Vector号称线程安全的主要原因,当然,什么事都是有利有弊,过犹不及。安全是安全了,但是每个方法,会进行同步操作,遇到那种高并发的场景,分分钟让人头秃,所以,没有最好的设计,只有最符合业务场景的设计。这也是1.2之后List出现后,对Vector进行修订的主要因素。

对的,你又说了,这明显其中有没被 synchronized 修饰的方法,比如 下面的几个方法:

public void add(int arg0,Object arg1){}
public boolean remove(Object arg0){}
public int indexOf(Object arg0){}
public void clear(){}
public boolean contains(Object arg0){}
public Enumeration elements(){}
public Spliterator spliterator(){}
           

是,小伙子绝对是孙悟空转世,火眼真睛,但是这些方法没有被synchronized关键词修饰,只是表象,我们来逐个看下这些方法的真是面目:

add(int ,Object)方法,是的,就是这么粗暴,直接调用了insertElementAt(element,int)方法,仅仅是反转了一下参数顺序而已。

/**
     * 在对应的位置插入元素,并且移动其他的元素到指定的位置
     * Inserts the specified element at the specified position in this Vector.
     * Shifts the element currently at that position (if any) and any
     * subsequent elements to the right (adds one to their indices).
     *
     * @param index index at which the specified element is to be inserted
     * @param element element to be inserted
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index > size()})
     * @since 1.2
     */
    public void add(int index, E element) {
        insertElementAt(element, index);
    }
           

remove(Object obj):同样,也只是调用了removeElement(obj)方法,没做其他什么处理:

/**
     * Removes the first occurrence of the specified element in this Vector
     * If the Vector does not contain the element, it is unchanged.  More
     * formally, removes the element with the lowest index i such that
     * {@code (o==null ? get(i)==null : o.equals(get(i)))} (if such
     * an element exists).
     *
     * @param o element to be removed from this Vector, if present
     * @return true if the Vector contained the specified element
     * @since 1.2
     */
    public boolean remove(Object o) {
        return removeElement(o);
    }
           

index(obj):调用了两个参数的重载方法,index(obj,0),从索引=0处,开始搜索查询指定的元素obj:

/**
     * Returns the index of the first occurrence of the specified element
     * in this vector, or -1 if this vector does not contain the element.
     * More formally, returns the lowest index {@code i} such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
     * or -1 if there is no such index.
     *
     * @param o element to search for
     * @return the index of the first occurrence of the specified element in
     *         this vector, or -1 if this vector does not contain the element
     */
    public int indexOf(Object o) {
        return indexOf(o, 0);
    }
           

clear(),调用removeAllElements(),清除所有的元素:

/**
     * Removes all of the elements from this Vector.  The Vector will
     * be empty after this call returns (unless it throws an exception).
     *
     * @since 1.2
     */
    public void clear() {
        removeAllElements();
    }
           

contains(obj),判断Vector中是否包含指定的元素:

/**
     * 通过index(o,0),判断Vector中是否包含指定的元素,包含,则返回true,不包含,返回false
     * Returns {@code true} if this vector contains the specified element.
     * More formally, returns {@code true} if and only if this vector
     * contains at least one element {@code e} such that
     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
     *
     * @param o element whose presence in this vector is to be tested
     * @return {@code true} if this vector contains the specified element
     */
    public boolean contains(Object o) {
        return indexOf(o, 0) >= 0;
    }
           

elements(),返回vector中所有的元素,和iterator()比较类似,对元素进行迭代返回的时候,也是经过了synchronized的修饰:

/**
     * 返回 vector 的枚举迭代器,返回的对象将生成vector中的所有项,第一个元素是vector中index=0的元素,之后index=1,以此类推。
     * Returns an enumeration of the components of this vector. The
     * returned {@code Enumeration} object will generate all items in
     * this vector. The first item generated is the item at index {@code 0},
     * then the item at index {@code 1}, and so on.
     *
     * @return  an enumeration of the components of this vector
     * @see     Iterator
     */
    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");
            }
        };
    }
           

spliterator()方法:

/**
     * 在vector上创建一个后期绑定以及快速失败的 Spliterator。
     * Creates a <em><a href="Spliterator.html#binding" target="_blank" rel="external nofollow" >late-binding</a></em>
     * and <em>fail-fast</em> {@link Spliterator} over the elements in this
     * list.
     *
     * <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
     * {@link Spliterator#SUBSIZED}, and {@link Spliterator#ORDERED}.
     * Overriding implementations should document the reporting of additional
     * characteristic values.
     *
     * @return a {@code Spliterator} over the elements in this list
     * @since 1.8
     */
    @Override
    public Spliterator<E> spliterator() {
        return new VectorSpliterator<>(this, null, 0, -1, 0);
    }
           

在1.2之后,Vector被纳入Java Collection Framework框架,实现了List接口,所以大部分方法都是和之前介绍的List中的方法相似,不再赘述。

经过比对,在Vector中,存在如下的方法,在List中不存在,我们来进行逐一介绍:

int lastIndexOf(Object arg0,int arg1){}
Object elementAt(int arg0){}
Enumeration elements(){}
void setSize(int arg0){}
int indexOf(Object arg0,int arg1){}
void copyInto(Object[] arg0){}
void addElement(Object arg0){}
void removeAllElements(){}
Object lastElement(){}
void removeElementAt(int arg0){}
Object firstElement(){}
void setElementAt(Object arg0,int arg1){}
void insertElementAt(Object arg0,int arg1){}
boolean removeElement(Object arg0){}
int capacity(){}
           

lastIndexOf(Object,index):该方法扩展了lastIndex(O)方法,可以在符合边界的基础上,在指定的搜索index基础上,向前找第一个符合要求的元素,然后进行返回。

/**
     * 从指定的index开始倒序查找,返回列表中指定元素的最后一次出现的索引。元素不存在,则返回-1.
     * Returns the index of the last occurrence of the specified element in
     * this vector, searching backwards from {@code index}, or returns -1 if
     * the element is not found.
     * More formally, returns the highest index {@code i} such that
     * <tt>(i&nbsp;&lt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i))))</tt>,
     * or -1 if there is no such index.
     *
     * @param o element to search for
     * @param index index to start searching backwards from
     * @return the index of the last occurrence of the element at position
     *         less than or equal to {@code index} in this vector;
     *         -1 if the element is not found.
     * @throws IndexOutOfBoundsException if the specified index is greater
     *         than or equal to the current size of this vector
     */
    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;
    }
           

elementAt(int arg0),返回指定索引上的元素:

/**
     * 和 get()相同,返回指定索引位置的元素,和get()不同之处在于,抛出的异常信息中,带了list最大的边界值
     * Returns the component at the specified index.
     *
     * <p>This method is identical in functionality to the {@link #get(int)}
     * method (which is part of the {@link List} interface).
     *
     * @param      index   an index into this vector
     * @return     the component at the specified index
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index >= size()})
     */
    public synchronized E elementAt(int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
        }

        return elementData(index);
    }
           

elements(),返回vector上的所有元素的枚举迭代器,在上边已经介绍过,为进行统一,此处再次进行介绍:

/**
     * 枚举迭代器
     * Returns an enumeration of the components of this vector. The
     * returned {@code Enumeration} object will generate all items in
     * this vector. The first item generated is the item at index {@code 0},
     * then the item at index {@code 1}, and so on.
     *
     * @return  an enumeration of the components of this vector
     * @see     Iterator
     */
    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");
            }
        };
    }
           

setSize(),故名思意,设置vector的size(),这是一个很神奇的方法,如果指定的长度大于vector原来的容量,则进行扩容,否则,将指定索引(包括)之后的所有元素,都设置为null:

/**
     * 设置vector的长度,如果指定的size大于当前的长度,则进行扩容,否则,将指定索引及以后的所有元素,设置为null。
     * Sets the size of this vector. If the new size is greater than the
     * current size, new {@code null} items are added to the end of
     * the vector. If the new size is less than the current size, all
     * components at index {@code newSize} and greater are discarded.
     *
     * @param  newSize   the new size of this vector
     * @throws ArrayIndexOutOfBoundsException if the new size is negative
     */
    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;
    }
           

indexOf(Object arg0,int arg1),和indexOf(Object)类似,返回元素第一次出现的索引位置,但是在此基础上做了扩展,可以指定搜索的起始位置,在此起始位置之后,第一次出现的元素的索引,更加的灵活:

/**
     * 和 lastIndexOf()对应,返回指定index之后,出现的第一个元素和指定元素相同的索引值。
     * Returns the index of the first occurrence of the specified element in
     * this vector, searching forwards from {@code index}, or returns -1 if
     * the element is not found.
     * More formally, returns the lowest index {@code i} such that
     * <tt>(i&nbsp;&gt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i))))</tt>,
     * or -1 if there is no such index.
     *
     * @param o element to search for
     * @param index index to start searching from
     * @return the index of the first occurrence of the element in
     *         this vector at position {@code index} or later in the vector;
     *         {@code -1} if the element is not found.
     * @throws IndexOutOfBoundsException if the specified index is negative
     * @see     Object#equals(Object)
     */
    public synchronized int indexOf(Object o, int index) {
        if (o == null) {
            for (int i = index ; i < elementCount ; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = index ; i < elementCount ; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }
           

copyInto(Object[] arg0),方法起一个好的名字,会节省更多的注释,从方法名上可以看到,该方法就是将当前vector对应的底层数组,复制到指定的数组中,当然,长度需要等于当前数组的长度:

其实就是 System.arraycopy()指定参数的固定用法。

/**
     * 将当前 Vector 底层对应的数组,复制到指定的 anArray中。
	 * 如果指定的数组长度不够,则会抛出 IndexOutOfBoundsException 异常。
	 * 如果插入的元素类型,和指定的数组的存储类型不相符,则抛出 ArrayStoreException 异常。
     * Copies the components of this vector into the specified array.
     * The item at index {@code k} in this vector is copied into
     * component {@code k} of {@code anArray}.
     *
     * @param  anArray the array into which the components get copied
     * @throws NullPointerException if the given array is null
     * @throws IndexOutOfBoundsException if the specified array is not
     *         large enough to hold all the components of this vector
     * @throws ArrayStoreException if a component of this vector is not of
     *         a runtime type that can be stored in the specified array
     * @see #toArray(Object[])
     */
    public synchronized void copyInto(Object[] anArray) {
        System.arraycopy(elementData, 0, anArray, 0, elementCount);
    }
           

addElement(Object arg0),添加指定的元素到Vector的末尾,功能上和add()方法相同:

/**
     * 将指定的元素,添加到当前list的末尾。
     * Adds the specified component to the end of this vector,
     * increasing its size by one. The capacity of this vector is
     * increased if its size becomes greater than its capacity.
     *
     * <p>This method is identical in functionality to the
     * {@link #add(Object) add(E)}
     * method (which is part of the {@link List} interface).
     *
     * @param   obj   the component to be added
     */
    public synchronized void addElement(E obj) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = obj;
    }
           

removeAllElements():删除所有的元素,功能上和clear()相同:

/**
     * 溢出所有的元素,并将长度设置为0.和 List 接口下的 clear()相同
     * Removes all components from this vector and sets its size to zero.
     *
     * <p>This method is identical in functionality to the {@link #clear}
     * method (which is part of the {@link List} interface).
     */
    public synchronized void removeAllElements() {
        modCount++;
        // Let gc do its work
        for (int i = 0; i < elementCount; i++)
            elementData[i] = null;

        elementCount = 0;
    }
           

 lastElement(),返回最后一个元素:

/**
     * 返回 Vector 的最后一个元素。index = size-1; Vector 为空,则抛出异常。
     * Returns the last component of the vector.
     *
     * @return  the last component of the vector, i.e., the component at index
     *          <code>size()&nbsp;-&nbsp;1</code>.
     * @throws NoSuchElementException if this vector is empty
     */
    public synchronized E lastElement() {
        if (elementCount == 0) {
            throw new NoSuchElementException();
        }
        return elementData(elementCount - 1);
    }
           

removeElementAt(int arg0),删除指定位置的元素:

/** 删除指定索引位置的元素,删除之后,在 Vector 中的比指定索引大或者相等的元素索引,都移动到比原来小的位置,vector的长度-1
     * Deletes the component at the specified index. Each component in
     * this vector with an index greater or equal to the specified
     * {@code index} is shifted downward to have an index one
     * smaller than the value it had previously. The size of this vector
     * is decreased by {@code 1}.
     *
     * <p>The index must be a value greater than or equal to {@code 0}
     * and less than the current size of the vector.
     *
     * removeElementAt(index)方法在功能上和List接口的remove()相同,但是remove()会返回原来存储的旧值。
     * <p>This method is identical in functionality to the {@link #remove(int)}
     * method (which is part of the {@link List} interface).  Note that the
     * {@code remove} method returns the old value that was stored at the
     * specified position.
     *
     * @param      index   the index of the object to remove
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index >= size()})
     */
    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 */
    }
           

firstElement(),返回第一个元素,如果Vector为空,则抛出异常:

/**
     * 返回第一个元素内容 index = 0 ;Vector 为空,则抛出异常。
     * Returns the first component (the item at index {@code 0}) of
     * this vector.
     *
     * @return     the first component of this vector
     * @throws NoSuchElementException if this vector has no components
     */
    public synchronized E firstElement() {
        if (elementCount == 0) {
            throw new NoSuchElementException();
        }
        return elementData(0);
    }
           

setElementAt(Object arg0,int arg1):在指定索引位置,设置元素:

/**
     * 给指定的index索引位置设值,该位置当前值会被丢弃。
     * Sets the component at the specified {@code index} of this
     * vector to be the specified object. The previous component at that
     * position is discarded.
     *
     * <p>The index must be a value greater than or equal to {@code 0}
     * and less than the current size of the vector.
     *
     * 该方法功能上和List接口的set(int ,Object) set(int,E)相同。注意set(int,Object)颠倒了参数的顺序,更匹配数组的用法。同时也要注意set()方法返回了旧值。
     * <p>This method is identical in functionality to the
     * {@link #set(int, Object) set(int, E)}
     * method (which is part of the {@link List} interface). Note that the
     * {@code set} method reverses the order of the parameters, to more closely
     * match array usage.  Note also that the {@code set} method returns the
     * old value that was stored at the specified position.
     *
     * @param      obj     what the component is to be set to
     * @param      index   the specified index
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index >= size()})
     */
    public synchronized void setElementAt(E obj, int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                     elementCount);
        }
        elementData[index] = obj;
    }
           

insertElementAt(Object arg0,int arg1) 向指定索引位置插入元素,其他位置的元素发生移动。

/**
     * insertElementAt() == add();add()直接调用了 insertElementAt();
     * Inserts the specified object as a component in this vector at the
     * specified {@code index}. Each component in this vector with
     * an index greater or equal to the specified {@code index} is
     * shifted upward to have an index one greater than the value it had
     * previously.
     *
     * <p>The index must be a value greater than or equal to {@code 0}
     * and less than or equal to the current size of the vector. (If the
     * index is equal to the current size of the vector, the new element
     * is appended to the Vector.)
     *
     * <p>This method is identical in functionality to the
     * {@link #add(int, Object) add(int, E)}
     * method (which is part of the {@link List} interface).  Note that the
     * {@code add} method reverses the order of the parameters, to more closely
     * match array usage.
     *
     * @param      obj     the component to insert
     * @param      index   where to insert the new component
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index > size()})
     */
    public synchronized void insertElementAt(E obj, int index) {
        modCount++;
        if (index > elementCount) {
            throw new ArrayIndexOutOfBoundsException(index
                                                     + " > " + elementCount);
        }
        ensureCapacityHelper(elementCount + 1); //首先扩充数组的容量+1
        System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);// 将指定索引及之后的元素,复制到原来索引+1的位置
        elementData[index] = obj;//将新的元素插入到指定的位置
        elementCount++;
    }
           

removeElement(Object arg0),删除元素:

/**
     * 删除在Vector中第一次出现的索引元素(即最小索引),如果元素在Vector中存在,原来大于指定索引的元素索引,-1.
     * Removes the first (lowest-indexed) occurrence of the argument
     * from this vector. If the object is found in this vector, each
     * component in the vector with an index greater or equal to the
     * object's index is shifted downward to have an index one smaller
     * than the value it had previously.
     *
     * <p>This method is identical in functionality to the
     * {@link #remove(Object)} method (which is part of the
     * {@link List} interface).
     *
     * @param   obj   the component to be removed
     * @return  {@code true} if the argument was a component of this
     *          vector; {@code false} otherwise.
     */
    public synchronized boolean removeElement(Object obj) {
        modCount++;
        int i = indexOf(obj);
        if (i >= 0) {
            removeElementAt(i);
            return true;
        }
        return false;
    }
           

capacity(),返回Vector的容量:

/**
     * 返回Vector的容量,和size()不同的是,size()返回的是Vector中的元素数量,capacity()返回的是当前不扩容前提下,可容纳的元素数量
     * Returns the current capacity of this vector.
     *
     * @return  the current capacity (the length of its internal
     *          data array, kept in the field {@code elementData}
     *          of this vector)
     */
    public synchronized int capacity() {
        return elementData.length;
    }


	//样例代码:
		Vector<String> vector = new Vector<String>() ;
		vector.ensureCapacity(200);
		vector.add("abc");
		System.out.println(vector.capacity());
		System.out.println(vector.size());
	//	打印出:
	//	200
	//	1
           

可以看下示例代码中,对vector容量设置的方法,ensureCapacity(200),设置Vector的大小,方法实现如下:

/**
     * 扩充 vector容量,确保列表可以至少容纳参数指定的特定元素列表中的所有元素。
     * Increases the capacity of this vector, if necessary, to ensure
     * that it can hold at least the number of components specified by
     * the minimum capacity argument.
     *
     * 如果当前容量小于指定的 minCapacity,那么容量会被扩充为较大的一个,通过重置被属性 elementData 所持有的内部数组。
     * 新数组的长度,将会是原有容量+capacityIncrement,除非 capacityIncrement小于0,这种情况下容量将被扩充为原有容量的两倍。
     * 如果扩充完之后,新数组的长度依然小于所需的 minCapacity,那么新的容量就会被设置为 minCapacity。
     * <p>If the current capacity of this vector is less than
     * {@code minCapacity}, then its capacity is increased by replacing its
     * internal data array, kept in the field {@code elementData}, with a
     * larger one.  The size of the new data array will be the old size plus
     * {@code capacityIncrement}, unless the value of
     * {@code capacityIncrement} is less than or equal to zero, in which case
     * the new capacity will be twice the old capacity; but if this new size
     * is still smaller than {@code minCapacity}, then the new capacity will
     * be {@code minCapacity}.
     *
     * @param minCapacity the desired minimum capacity
     */
    public synchronized void ensureCapacity(int minCapacity) {
        if (minCapacity > 0) {
            modCount++;
            ensureCapacityHelper(minCapacity);
        }
    }
	
    /**
     * 我们可以看到,这个方法是非同步方法,为什么可以这样呢,是因为他的调用方 ensureCapacity()是同步方法,该方法作为私有方法被内部调用,无需再额外增加同步浪费资源。
     * This implements the unsynchronized semantics of ensureCapacity.
     * Synchronized methods in this class can internally call this
     * method for ensuring capacity without incurring the cost of an
     * extra synchronization.
     *
     * @see #ensureCapacity(int)
     */
    private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
	
	
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
		
		// 如果 capacityIncrement>0,那么新的容量就是原有容量 oldCapacity+capacityIncrement,否则容量会变成 oldCapacity+oldCapacity,即变成原有容量的两倍。
        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);
    }
           

在其中,可以看到两点,值得我们注意:

1、在 ensureCapacity()方法实现中,有一个modCount++;

这个字段有什么作用呢,其实还是从名字,可以看出来部分端倪,mod应该为modify的缩写,取修改之意,Count++,就是自增,合起来就是修改次数的累加之和。具体有什么用呢,来看该字段的注释:

/**
     * 记录了当前list结构修改的次数
     * The number of times this list has been <i>structurally modified</i>.
     * Structural modifications are those that change the size of the
     * list, or otherwise perturb it in such a fashion that iterations in
     * progress may yield incorrect results.
     *
     * 如果迭代器在迭代期间,该值发生了意外改变,即有其他并发线程在修改当前list,那么就会抛出 ConcurrentModificationException 异常。
     * <p>This field is used by the iterator and list iterator implementation
     * returned by the {@code iterator} and {@code listIterator} methods.
     * If the value of this field changes unexpectedly, the iterator (or list
     * iterator) will throw a {@code ConcurrentModificationException} in
     * response to the {@code next}, {@code remove}, {@code previous},
     * {@code set} or {@code add} operations.  This provides
     * <i>fail-fast</i> behavior, rather than non-deterministic behavior in
     * the face of concurrent modification during iteration.
     *
     * 子类是否使用该字段是可选的,如果子类希望提供一个快速失败的迭代器(以及列表迭代器),
	 * 只需要在add/remove(以及其他可能对列表结构发生改变的方法中)对该字段进行加操作。
	 * 对于add/remove的一次调用,对于该字段的增加不能超过1.否则列表会抛出伪装的 ConcurrentModificationExceptions 异常。
	 * 如果子类实现不希望提供快速失败迭代器,可以忽略这个字段。
     * <p><b>Use of this field by subclasses is optional.</b> If a subclass
     * wishes to provide fail-fast iterators (and list iterators), then it
     * merely has to increment this field in its {@code add(int, E)} and
     * {@code remove(int)} methods (and any other methods that it overrides
     * that result in structural modifications to the list).  A single call to
     * {@code add(int, E)} or {@code remove(int)} must add no more than
     * one to this field, or the iterators (and list iterators) will throw
     * bogus {@code ConcurrentModificationExceptions}.  If an implementation
     * does not wish to provide fail-fast iterators, this field may be
     * ignored.
     */
    protected transient int modCount = 0;
           

可以看到,主要是为了统计一些改变数据结构的方法,诸如add/remove/等等,这些方法的调用次数,用来在创建迭代器之后,进行遍历的整个声明周期中,作为当前结构是否发生意外修改的一个依据,如果发现当前list的长度和预期的不符,表明已经发生了修改,那么就会抛出 ConcurrentModificationException 异常。来看具体的实现源码:

首先看创建迭代器的源码,iterator():

public synchronized Iterator<E> iterator() {
        return new Itr();
    }
           

方法返回了一个Itr内部类的实例,再来看该类源码:

private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        public boolean hasNext() {
            // Racy but within spec, since modifications are checked
            // within or after synchronization in next/previous
            return cursor != elementCount;
        }

        public E next() {
            synchronized (Vector.this) {
                checkForComodification(); // 同步遍历该 Vector过程中,会对该Vector进行检查
                int i = cursor;
                if (i >= elementCount)
                    throw new NoSuchElementException();
                cursor = i + 1;
                return elementData(lastRet = i);
            }
        }

        public void remove() {
            if (lastRet == -1)
                throw new IllegalStateException();
            synchronized (Vector.this) {
                checkForComodification();
                Vector.this.remove(lastRet);
                expectedModCount = modCount;
            }
            cursor = lastRet;
            lastRet = -1;
        }

        @Override
        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            synchronized (Vector.this) {
                final int size = elementCount;
                int i = cursor;
                if (i >= size) {
                    return;
                }
        @SuppressWarnings("unchecked")
                final E[] elementData = (E[]) Vector.this.elementData;
                if (i >= elementData.length) {
                    throw new ConcurrentModificationException();
                }
                while (i != size && modCount == expectedModCount) {
                    action.accept(elementData[i++]);
                }
                // update once at end of iteration to reduce heap write traffic
                cursor = i;
                lastRet = i - 1;
                checkForComodification();
            }
        }

        final void checkForComodification() {
			// 检查主要逻辑,就是判断当前的值(可以外部修改)和预期的值(在创建iterator时已经被固定初始化)是否相同,
			// 如果不同,那就代表除了当前iterator之外,有其他的操作对该list进行修改,就会抛出 ConcurrentModificationException 异常。
            if (modCount != expectedModCount) 
                throw new ConcurrentModificationException();
        }
    }
           

 从 上述内部类中 checkForComodification()方法的实现,我们也了解了流传江湖已久的 ConcurrentModificationException 的发生机理。

2、ensureCapacity()方法中,调用了ensureCapacityHelper()方法,该方法为非同步方法。

那么问题可能来了,就是作为以线程安全著称的Vector,对Vector进行扩容这么重要的操作,怎么没有 synchronized 关键字修饰呢?

其实原因在上述ensureCapacity()源码解析中,已经有了说明,为了进一步说明和加深记忆,在此处再重复说明一次。

原因其实很简单,就是虽然 ensureCapacityHelper()不是线程安全的,但是它是内部私有方法,外部能独立调用,在类内部实现中,我们可以看到,它的调用方ensureCapacity()是线程安全的,所以无需再额外的增加线程安全控制的开销。

对于List接口下,还有一篇Stack的介绍,就可以结束了,该接口下,其他主要类源码的分析有这些:

其他相关文章:

Java集合类框架源码分析 之 Stack源码解析 【9】

Java集合类框架源码分析 之 Vector源码解析 【8】

Java集合类框架源码分析 之 AttributeList源码解析 【7】

Java集合类框架源码分析 之 RoleList源码解析 【6】

Java集合类框架源码分析 之 CopyOnWriteArrayList源码解析 【5】

Java集合类框架源码分析 之 LinkedList源码解析 【4】

Java集合类框架源码分析 之 ArrayList源码解析 【3】

Java集合类框架源码分析 之 接口中是否可以有方法实现 【2】

Java集合类框架源码分析 之 List 接口源码分析 【1】