按照国际惯例,还是先来看下类简介,有助于从整体上对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 ? get(i)==null : 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 ? e==null : 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 <= index && (o==null ? get(i)==null : 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 >= index && (o==null ? get(i)==null : 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() - 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】