Vector源码分析
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vector源码分析相关的知识,希望对你有一定的参考价值。
源码版本为JDK1.7.0_75。
public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
Vector继承了AbstractList,实现了List接口,可以被当作list使用;实现了RandomAccess接口,该接口是一个标记接口,表明该类支持快速随机访问;实现了Cloneable接口,说明该类可以被克隆;实现了Serializable接口,说明该类可以支持序列化(看到网上有说vector类没有实现Serializable接口,可是明明已经实现了【implements java.io.Serializable】??)。Vector中的大部分方法使用了synchronized,故Vector是同步的。
使用了synchronized修饰的方法包括copyInto、trimToSize、ensureCapacity、setSize、capacity、size、isEmpty、indexOf、lastIndexOf、elementAt、firstElement、lastElement、setElementAt、removeElementAt、insertElementAt、addElement、removeElement、removeAllElements、clone、toArray、get、set、add、remove、containsAll、addAll、removeAll、retainAll、addAll、equals、hashCode、toString、subList、removeRange、writeObject、listIterator、iterator等。
成员变量
可以看出Vector类使用数组实现。
/** * 该数组保存vecor内容。vector的容量是该数组的长度,该数组足够大包含vector所有元素。 * The array buffer into which the components of the vector are * stored. The capacity of the vector is the length of this array buffer, * and is at least large enough to contain all the vector‘s elements. * * <p>Any array elements following the last element in the Vector are null. * * @serial */ protected Object[] elementData; /** * vector对象的元素数目,有可能出现elementData开辟了空间,但vector没有元素的情况。 * The number of valid components in this {@code Vector} object. * Components {@code elementData[0]} through * {@code elementData[elementCount-1]} are the actual items. * * @serial */ protected int elementCount; /** * 当elementData大小大于vector容量时,容量自动增长倍数。若容量增长小于等于0,则vector容量在每次需要扩充时,加倍增长。 * The amount by which the capacity of the vector is automatically * incremented when its size becomes greater than its capacity. If * the capacity increment is less than or equal to zero, the capacity * of the vector is doubled each time it needs to grow. * * @serial */ protected int capacityIncrement; /** use serialVersionUID from JDK 1.0.2 for interoperability */ private static final long serialVersionUID = -2767605614048989439L;
构造函数
/** * 构造一个指定了初始容量和容量增量的空vector * Constructs an empty vector with the specified initial capacity and * capacity increment. * * @param initialCapacity the initial capacity of the vector * @param capacityIncrement the amount by which the capacity is * increased when the vector overflows * @throws IllegalArgumentException if the specified initial capacity * is negative */ public Vector(int initialCapacity, int capacityIncrement) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; this.capacityIncrement = capacityIncrement; } /** * 构造一个指定了初始容量的空vecor * Constructs an empty vector with the specified initial capacity and * with its capacity increment equal to zero. * * @param initialCapacity the initial capacity of the vector * @throws IllegalArgumentException if the specified initial capacity * is negative */ public Vector(int initialCapacity) { this(initialCapacity, 0); } /** * 构造一个空vector,默认情况下初始容量大小为10,增量为0. * Constructs an empty vector so that its internal data array * has size {@code 10} and its standard capacity increment is * zero. */ public Vector() { this(10); } /** * 构造一个包含特定集合元素的vector。 * Constructs a vector containing the elements of the specified * collection, in the order they are returned by the collection‘s * iterator. * * @param c the collection whose elements are to be placed into this * vector * @throws NullPointerException if the specified collection is null * @since 1.2 */ 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); }
方法
扩充容量
/** * 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. * * <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); } } /** * 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); } /** * The maximum size of array to allocate. * Some VMs reserve some header words in an array. * Attempts to allocate larger arrays may result in * OutOfMemoryError: Requested array size exceeds VM limit */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; /** * 若capacityIncrement大于0,则至少增加capacityIncrement大小;否则至少增加 * elementData.length大小。 */ private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; 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); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
容量和长度大小
elementData.length指elementData数组的长度,而elementCount指vector实际元素个数,两者不一定相等。方法capacity指所给的空间,因此返回的是elementData数组的长度,而方法size则返回的是vector元素个数,即elementCount。方法isEmpty判断的是vector中是否有元素,而不是判断是否有空间,因此使用的是变量elementCount。
/** * 返回vector当前容量 * 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元素个数 * Returns the number of components in this vector. * * @return the number of components in this vector */ public synchronized int size() { return elementCount; } /** * 测试vector是否没有包含元素 * Tests if this vector has no components. * * @return {@code true} if and only if this vector has * no components, that is, its size is zero; * {@code false} otherwise. */ public synchronized boolean isEmpty() { return elementCount == 0; }
枚举
该方法返回一个实现了接口Enumeration的匿名内部类,Enumeration接口需要实现hasMoreElements和nextElement两个方法。其中nextElement方法中的synchronized (Vector.this) {}表示同步块,表示当两个并发线程访问同一个vector对象的同步代码块时,一个时间内只能有一个线程得到执行,另一个线程要等待当前线程执行完这个代码块以后才能执行该代码块。
/** * 返回对该vector元素进行枚举的Enumeration类。 * 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"); } }; }
添加元素时,首先都需要对容量进行扩充
/** * 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); System.arraycopy(elementData, index, elementData, index + 1, elementCount - index); elementData[index] = obj; elementCount++; } /** * 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; } /** * Appends the specified element to the end of this Vector. * * @param e element to be appended to this Vector * @return {@code true} (as specified by {@link Collection#add}) * @since 1.2 */ public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; } /** * 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); }
克隆
方法clone并没有将elementCount和capacityIncrement的值也复制到新的vector中。
/** * Returns a clone of this vector. The copy will contain a * reference to a clone of the internal data array, not a reference * to the original internal data array of this {@code Vector} object. * * @return a clone of this vector */ public synchronized Object clone() { try { @SuppressWarnings("unchecked") Vector<E> v = (Vector<E>) super.clone(); v.elementData = Arrays.copyOf(elementData, elementCount); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn‘t happen, since we are Cloneable throw new InternalError(); } }
大容量操作(Bulk Operations)
containsAll、addAll、removeAll、retainAll
/** * Returns the hash code value for this Vector. */ public synchronized int hashCode() { return super.hashCode(); } |
该方法通过集合Collections.synchronizedList将返回的list转换为一个线程安全的类。
/** * Returns a view of the portion of this List between fromIndex, * inclusive, and toIndex, exclusive. (If fromIndex and toIndex are * equal, the returned List is empty.) The returned List is backed by this * List, so changes in the returned List are reflected in this List, and * vice-versa. The returned List supports all of the optional List * operations supported by this List. * * <p>This method eliminates the need for explicit range operations (of * the sort that commonly exist for arrays). Any operation that expects * a List can be used as a range operation by operating on a subList view * instead of a whole List. For example, the following idiom * removes a range of elements from a List: * <pre> * list.subList(from, to).clear(); * </pre> * Similar idioms may be constructed for indexOf and lastIndexOf, * and all of the algorithms in the Collections class can be applied to * a subList. * * <p>The semantics of the List returned by this method become undefined if * the backing list (i.e., this List) is <i>structurally modified</i> in * any way other than via the returned List. (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.) * * @param fromIndex low endpoint (inclusive) of the subList * @param toIndex high endpoint (exclusive) of the subList * @return a view of the specified range within this List * @throws IndexOutOfBoundsException if an endpoint index value is out of range * {@code (fromIndex < 0 || toIndex > size)} * @throws IllegalArgumentException if the endpoint indices are out of order * {@code (fromIndex > toIndex)} */ public synchronized List<E> subList(int fromIndex, int toIndex) { return Collections.synchronizedList(super.subList(fromIndex, toIndex), this); } |
总结:
1、Vector有四个不同的构造方法。无参构造方法的容量默认为10,增量为0.
2、扩充容量的方法ensureCapacity,与ArrayList类似,但Vector可以自定义至少扩充的增量(capacityIncrement)。
3、Vector是同步的,而ArrayList、LinkedList是非同步的。为了保证一些方法的同步,使用了synchronized修饰;保证一些代码的执行的同步,使用了同步块;保证list的同步,使用了Collection.synchronizedList方法。
4、与ArrayList、LinkedList类似,Vector允许元素为null
5、Vector的容量(capacity)和大小(size)是有区别的。
以上是关于Vector源码分析的主要内容,如果未能解决你的问题,请参考以下文章