JDK8源码阅读笔记
切换暗/亮/自动模式 切换暗/亮/自动模式 切换暗/亮/自动模式 返回首页

Vector




Vector类实现了一个可增长的对象数组。像数组一样,它包含可以使用整数索引访问的组件。但是,Vector的大小可以根据需要增加或缩小,以在Vector创建后能够添加和删除项目。

每个vector都尝试通过维护一个capacity和一个capacityIncrement来优化存储管理。capacity始终至少与vector大小一样大,通常它会更大,因为随着组件添加到vector中,vector的存储以块的形式增加capacityIncrement的大小。一个应用程序可以在插入大量组件之前增加一个vector的容量,这将减少增量重新分配的次数。

此类的iteratorlistIterator方法返回的迭代器是“快速失败”的:如果在创建迭代器后的任何时间对vector进行结构上的修改,除了通过迭代器自己的removeadd方法之外,迭代器将抛出一个ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒任意、不确定行为的风险。elements方法返回的Enumeration不是快速失败的。

请注意,无法保证迭代器的快速失败行为,因为一般而言,在存在非同步地并发修改的情况下不可能做出任何严格保证。快速失败的迭代器会尽最大努力抛出ConcurrentModificationException。因此,编写一个依赖于这个异常来保证其正确性的程序是错误的:迭代器的快速失败行为应该只用于检测错误。

从 Java 2 平台 v1.2 开始,该类经过改造实现了List接口,使其成为“Java 集合框架”的成员。与新的集合实现不同,Vector是同步的。如果不需要线程安全的实现,建议使用ArrayList代替Vector


1. protected Object[] elementData;

存储vector组件的数组缓冲区。vector的容量是这个数组缓冲区的长度,并且至少足够包含vector的所有元素。

Vector中最后一个元素之后的任何数组元素都为空。


2. protected int elementCount;

Vector对象中的有效组件数。组件elementData[0]elementData[elementCount-1]是实际的条目。


3. protected int capacityIncrement;

当vector的大小要变得大于其容量时,vector的容量自动增加的量。如果容量增量小于或等于零,则每次需要增长时,vector的容量都会增加一倍。


4. private static final long serialVersionUID = -2767605614048989439L;

使用 JDK 1.0.2 中的 serialVersionUID 实现互通性。


5. public Vector(int initialCapacity, int capacityIncrement)

构造一个具有指定初始容量和容量增量的空vector。

其源码如下:

public Vector(int initialCapacity, int capacityIncrement) {
		// 调用AbstractList()
    super();
		// 初始容量不可小于0
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
		// 初始化组件数组,也即元素数组
    this.elementData = new Object[initialCapacity];
		// 设定容量增量
    this.capacityIncrement = capacityIncrement;
}

6. public Vector(int initialCapacity)

构造一个具有指定初始容量且容量增量为零的空vector。

源码如下:

public Vector(int initialCapacity) {
    this(initialCapacity, 0);
}

7. public Vector()

构造一个空vector,使其内部数据数组的大小为10并且其标准容量增量为零。

源码如下:

public Vector() {
    this(10);
}

8. public Vector(Collection<? extends E> c)

构造一个包含指定集合元素的vector,按照集合的迭代器返回的顺序。

源码如下:

public Vector(Collection<? extends E> c) {
		// 将参数中给定集合转化为数组
    Object[] a = c.toArray();
		// 数组长度即本Vector实例的元素数量
    elementCount = a.length;
		// 如果指定集合是ArrayList,则数组a可直接赋值给本Vector实例用于存储数据的数组
    if (c.getClass() == ArrayList.class) {
        elementData = a;
    } else {
				// 非ArrayList,可能与Vector实现差异较大,此处进行数组复制
        elementData = Arrays.copyOf(a, elementCount, Object[].class);
    }
}

9. public synchronized void copyInto(Object[] anArray)

将此vector的组件(即元素)复制到指定的数组中。此vector中索引k处的项目被复制到anArrayk位置。

源码如下:

public synchronized void copyInto(Object[] anArray) {
    System.arraycopy(elementData, 0, anArray, 0, elementCount);
}

10. public synchronized void trimToSize()

将此vector的容量修剪为vector的当前大小。如果此vector的容量大于其当前大小,则通过将其内部数据数组替换为较小的数组,将容量更改为等于大小,该数组保存在字段elementData中。应用程序可以使用此操作来最小化vector的存储。

public synchronized void trimToSize() {
		// 增加修改次数
    modCount++;
		// 取出当前数组长度
    int oldCapacity = elementData.length;
		// 如果当前元素个数 小于 当前数组长度
    if (elementCount < oldCapacity) {
				// 复制当前数组存放了数据的部分,也即丢弃数组后面未存放元素的部分
        elementData = Arrays.copyOf(elementData, elementCount);
    }
}

11. public synchronized void ensureCapacity(int minCapacity)

如有必要,增加此vector的容量,以确保它至少可以容纳由最小容量参数指定的组件数量。

如果此vector的当前容量小于minCapacity,则通过将其保存在字段elementData中的内部数据数组替换为更大的数组来增加其容量。新数据数组的大小为旧大小加上capacityIncrement,除非capacityIncrement的值小于或等于0,在这种情况下,新容量将是旧容量的两倍;但如果这个新大小仍然小于minCapacity,那么新容量将是minCapacity

源码如下:

public synchronized void ensureCapacity(int minCapacity) {
    if (minCapacity > 0) {
				// 增加修改次数
        modCount++;
				// 调用确保容量方法的非同步版本
        ensureCapacityHelper(minCapacity);
    }
}

12. private void ensureCapacityHelper(int minCapacity)

本方法实现了ensureCapacity的非同步版本。本类中的同步方法可以在内部调用此方法以确保容量,而不会产生额外同步的成本。

源码如下:

private void ensureCapacityHelper(int minCapacity) {
    // overflow-conscious code
		// 如果参数中的最小容量大于当前vector存放数据的数组容量,则调用grow方法增大数组的容量
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

13. private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

要分配的数组的最大大小。

一些 VM 在数组中保留一些头字。

尝试分配更大的数组可能会导致OutOfMemoryError:请求的数组大小超出 VM 限制


14. private void grow(int minCapacity)

增加数组elementData大小。

源码如下:

private void grow(int minCapacity) {
    // overflow-conscious code
		// 取出当前数组elementData的容量
    int oldCapacity = elementData.length;
		// 如果容量增量大于0,则 新数组容量 = 旧数组容量 + 容量增量
		// 否则, 新数组容量 = 旧数组容量 + 旧数组容量
    int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                     capacityIncrement : oldCapacity);
		// 经上述逻辑计算出的新数组容量如果仍小于参数中指定的最小容量,则新数组容量直接取参数中的最小容量
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
		// 经上述逻辑计算出的新数组容量如果大于Vector限定的数组最大数量,则调用获取最大容量方法
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
		// 将elementData复制到扩容后的新数组
    elementData = Arrays.copyOf(elementData, newCapacity);
}

15. private static int hugeCapacity(int minCapacity)

获取巨大的容量。

源码如下:

private static int hugeCapacity(int minCapacity) {
		// 如果最小容量小于0,则抛出OutOfMemoryError
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
		// 如果最小容量大于Vector设定的最大数组容量,则巨大容量取Integer的最大值
		// 否则,巨大容量取Vector设定的最大数组容量
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

16. public synchronized void setSize(int newSize)

设置此vector的大小。如果新大小大于当前大小,则往此vector的末尾添加null。如果新大小小于当前大小,则索引newSize位置及其之后的所有组件都将被丢弃。

源码如下:

public synchronized void setSize(int newSize) {
		// 增加修改次数
    modCount++;
		// 如果新大小大于当前元素个数,则调用ensureCapacityHelper确保数组容量
    if (newSize > elementCount) {
        ensureCapacityHelper(newSize);
    } else {
				// 新大小小于等于当前元素个数,则遍历数组从新大小到元素个数-1位置的部分
				// 将遍历到的每个元素都置为null
        for (int i = newSize ; i < elementCount ; i++) {
            elementData[i] = null;
        }
    }
		// 将元素个数置为新大小
    elementCount = newSize;
}

17. public synchronized int capacity()

返回此vector的当前容量。

当前容量:其内部数据数组(即此vector的elementData字段)的长度。

源码如下:

public synchronized int capacity() {
    return elementData.length;
}

18. public synchronized int size()

返回此vector中的组件数(即元素个数)。

源码如下:

public synchronized int size() {
    return elementCount;
}

19. public synchronized boolean isEmpty()

测试此vector是否没有组件。

源码如下:

public synchronized boolean isEmpty() {
    return elementCount == 0;
}

20. public Enumeration<E> elements()

返回此vector的组件的枚举。返回的Enumeration对象将生成此向量中的所有项目。生成的第一项是索引0处的项,然后是索引1处的项,依此类推。

源码如下:

public Enumeration<E> elements() {
		// 因为Enumeration是一个接口,所以此处返回的是一个它的匿名内部类
		// 该接口有两个方法:hasMoreElements()、nextElement()
    return new Enumeration<E>() {
				// 从0开始计数,此处count可以理解为游标
        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");
        }
    };
}

21. public boolean contains(Object o)

如果此vector包含指定的元素,则返回true。更正式地说,当且仅当此vector包含至少一个元素e使得(o==null ? e==null : o.equals(e))时才返回true

源码如下:

public boolean contains(Object o) {
		// 调用indexOf方法判断指定元素在数组中的索引位置是否大于等于0
    return indexOf(o, 0) >= 0;
}

22. public int indexOf(Object o)

返回指定元素在此vector中第一次出现的索引,如果此向量不包含该元素,则返回-1。更正式地说,返回最小索引i使得(o==null ? get(i)==null : o.equals(get(i))),或者如果有是没有这样的索引则返回-1

源码如下:

public int indexOf(Object o) {
		// 从索引位置0处开始匹配
    return indexOf(o, 0);
}

23. public synchronized int indexOf(Object o, int index)

返回此vector中指定元素第一次出现的索引,从index开始搜索,如果未找到该元素,则返回-1。更正式地说,返回最小索引i使得(i >= index && (o==null ? get(i)==null : o.equals(get(i)))),如果没有这样的索引,则返回-1

源码如下:

public synchronized int indexOf(Object o, int index) {
    if (o == null) {
				// 指定对象为null,则遍历数组找到元素为null的索引位置
        for (int i = index ; i < elementCount ; i++)
            if (elementData[i]==null)
                return i;
    } else {
				// 指定对象不为null,则遍历数组找到equals为true的元素的索引位置
        for (int i = index ; i < elementCount ; i++)
            if (o.equals(elementData[i]))
                return i;
    }
		// 找不到则返回-1
    return -1;
}

24. public synchronized int lastIndexOf(Object o)

返回指定元素在此vector中最后一次出现的索引,如果此vector不包含该元素,则返回-1。更正式地,返回最大索引i使得(o==null ? get(i)==null : o.equals(get(i))),或者如果没有这样的索引则返回-1

源码如下:

public synchronized int lastIndexOf(Object o) {
    return lastIndexOf(o, elementCount-1);
}

25. public synchronized int lastIndexOf(Object o, int index)

返回指定元素在此vector中最后一次出现的索引,从index开始向前搜索(即向索引变小的方向搜索),如果未找到该元素,则返回-1。更正式地说,返回最高索引i使得(i <= index && (o==null ? get(i)==null : o.equals(get(i)))),如果没有这样的索引则返回-1

源码如下:

public synchronized int lastIndexOf(Object o, int index) {
		// 检查开始索引是否大于等于元素个数,如果是则抛出数组越界异常
    if (index >= elementCount)
        throw new IndexOutOfBoundsException(index + " >= "+ elementCount);

		// 和indexOf方法类似,指定对象是否为空走不同的逻辑
    if (o == null) {
				// 从index位置开始,一直往前遍历(索引变小的方向)
        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;
    }
		// 未找到,则返回-1
    return -1;
}

26. public synchronized E elementAt(int index)

返回指定索引处的组件(即元素)。

此方法在功能上与get(int)方法相同(get(int)List接口的方法之一)。

源码如下:

public synchronized E elementAt(int index) {
		// 数组越界检查
    if (index >= elementCount) {
        throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
    }

		// 调用elementData方法
    return elementData(index);
}

27. public synchronized E firstElement()

返回此vector的第一个组件(索引0处的项目)。

源码如下:

public synchronized E firstElement() {
    if (elementCount == 0) {
        throw new NoSuchElementException();
    }
		// 没有特殊逻辑,就是从数组中根据索引0取数据
    return elementData(0);
}

28. public synchronized E lastElement()

返回vector的最后一个组件。

源码如下:

public synchronized E lastElement() {
    if (elementCount == 0) {
        throw new NoSuchElementException();
    }
		// 返回elementData数组中最后一个元素,对应索引位置为:元素个数 - 1
    return elementData(elementCount - 1);
}

29. public synchronized void setElementAt(E obj, int index)

将此vector的指定index处的组件设置为指定对象,该位置之前的组件将被丢弃。

该索引必须大于或等于0且小于vector的当前大小。

此方法在功能上与set(int, E)方法(它是List接口的方法之一)相同。请注意,set方法颠倒了参数的顺序,以更紧密地匹配数组用法。另请注意,set方法会返回存储在指定位置的旧值。

源码如下:

public synchronized void setElementAt(E obj, int index) {
    if (index >= elementCount) {
        throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                 elementCount);
    }
    elementData[index] = obj;
}

30. public synchronized void removeElementAt(int index)

删除指定索引处的组件。此vector中索引大于或等于指定index的每个组件向前移动,使其索引比之前的值小 1。这个vector的大小减少1

索引必须是大于或等于0且小于vector的当前大小的值。

此方法在功能上与remove(int)方法(它是List接口的一部分)相同。需要注意,remove方法会返回存储在指定位置的旧值。

源码如下:

public synchronized void removeElementAt(int index) {
		// 增加修改次数
    modCount++;
		// 校验指定的索引index是否出于合理区间(即:大于等于0且小于元素个数)
    if (index >= elementCount) {
        throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                 elementCount);
    }
    else if (index < 0) {
        throw new ArrayIndexOutOfBoundsException(index);
    }
		// 计算出所需要异动位置的元素个数
    int j = elementCount - index - 1;
    if (j > 0) {
				// 进行数组复制
				// 将elementData数组的“index+1”及之后的元素复制到elementData数组的“index”处及之后的位置
				// 复制元素的个数为j
        System.arraycopy(elementData, index + 1, elementData, index, j);
    }
		// 元素个数减一
    elementCount--;
		// 将末尾的元素置为null,以使其可被垃圾回收
    elementData[elementCount] = null; /* to let gc do its work */
}

31. public synchronized void insertElementAt(E obj, int index)

将指定对象作为组件插入此vector中指定index处。此vector中索引大于或等于指定index的每个组件向后移动,使其索引比之前的值大 1。

索引必须是大于等于0且小于等于vector的当前大小的值。(如果索引等于vector的当前大小,则新元素将追加到当前vector。)

此方法在功能上与add(int, E)方法(它是List接口的一部分)相同。需要注意,add方法颠倒了参数的顺序,以更接近数组用法。

源码如下:

public synchronized void insertElementAt(E obj, int index) {
		// 修改次数加1
    modCount++;
		// 校验指定的索引index是否在合理的区间内
    if (index > elementCount) {
        throw new ArrayIndexOutOfBoundsException(index
                                                 + " > " + elementCount);
    }
		// 确保vector容量足够
    ensureCapacityHelper(elementCount + 1);
		// 执行数组复制,将elementData数组index及之后的元素复制到elementData的index+1处及之后的位置
		// 复制的元素个数为元素个数-指定索引index
    System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
		// 此时给index位置替换元素为指定的元素obj
    elementData[index] = obj;
		// 元素个数加1
    elementCount++;
}

32. public synchronized void addElement(E obj)

将指定的组件添加到此vector的末尾,将其大小增加 1。如果该vector的大小变得大于其容量,则该vector的容量会增加。

此方法在功能上与add(E)方法(它是List接口的一部分)相同。

源码如下:

public synchronized void addElement(E obj) {
		// 修改次数加1
    modCount++;
		// 确保容量足够(不够的话会进行扩容)
    ensureCapacityHelper(elementCount + 1);
		// 将指定元素拼接到vector的末尾
    elementData[elementCount++] = obj;
}

33. public synchronized boolean removeElement(Object obj)

从此vector中删除指定参数的第一次(最低索引)出现。如果在此vector中找到对象,则向量中索引大于或等于该指定对象索引的每个元素将向前移动,使其索引比之前的值减1。

此方法在功能上与remove(Object)方法(它是List接口的一部分)相同。

源码如下:

public synchronized boolean removeElement(Object obj) {
		// 修改次数加1
    modCount++;
		// 找到指定元素的索引位置(最小的那个)
    int i = indexOf(obj);
		// 如果找到了,则删除并返回true,否则返回false
    if (i >= 0) {
				// 删除指定索引位置的元素
        removeElementAt(i);
        return true;
    }
    return false;
}

34. public synchronized void removeAllElements()

删除此vector中的所有组件并将其大小设置为零。

此方法在功能上与clear方法(它是List接口的一部分)相同。

源码如下:

public synchronized void removeAllElements() {
		// 修改次数加1
    modCount++;
    // Let gc do its work
		// 遍历数组,将所有元素置为null,以使其可被垃圾回收
    for (int i = 0; i < elementCount; i++)
        elementData[i] = null;

		// 将元素个数置为0
    elementCount = 0;
}

35. public synchronized Object clone()

返回此vector的克隆。该副本将包含对内部数据数组副本的引用,而不是对这个Vector对象的原始内部数据数组的引用。

源码如下:

public synchronized Object clone() {
    try {
				// 调用Object的clone方法获取一个Vector对象,但此时持有元素的数据数组未被复制
        @SuppressWarnings("unchecked")
            Vector<E> v = (Vector<E>) super.clone();
				// 将持有元素的数据数组复制一份,并赋值给上面新得到的Vector对象
        v.elementData = Arrays.copyOf(elementData, elementCount);
				// 修改次数赋值为0
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

36. public synchronized Object[] toArray()

以正确的顺序返回包含此Vector中所有元素的数组。

源码如下:

public synchronized Object[] toArray() {
		// 返回的是内部数据数组的副本
    return Arrays.copyOf(elementData, elementCount);
}

37. public synchronized <T> T[] toArray(T[] a)

以正确的顺序返回包含此Vector中所有元素的数组;返回数组的运行时类型是指定数组的类型。如果Vector适合指定的数组,则在其中返回。否则,将使用指定数组的运行时类型和此Vector的大小分配一个新数组。

如果Vector适合指定的数组并有剩余空间(即,该数组的元素比Vector多),则紧跟Vector末尾的数组中的元素将设置为null。(如果调用者知道Vector不包含任何空元素,这对于确定Vector的长度很有用。)

源码如下:

@SuppressWarnings("unchecked")
public synchronized <T> T[] toArray(T[] a) {
		// 如果指定的数组a的大小小于当前Vector对象的元素个数,则直接数组复制到一个新的数组并返回
    if (a.length < elementCount)
        return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());

		// 指定数组a的大小大于等于当前Vector对象的元素个数,说明其可以承载当前Vector的所有元素
		// 将Vector对象中持有元素的数据数组复制到指定的数组a
    System.arraycopy(elementData, 0, a, 0, elementCount);

		// 如果指定的数组a的容量大于当前Vector对象的大小,则在数组a的最后一个元素的下一个元素设置为null(也即elementCount索引位置)
    if (a.length > elementCount)
        a[elementCount] = null;

    return a;
}

38. E elementData(int index)

获取指定索引位置的元素。

源码如下:

@SuppressWarnings("unchecked")
E elementData(int index) {
		// 直接从数组中取出指定索引位置的元素
    return (E) elementData[index];
}

39. public synchronized E get(int index)

返回此Vector中指定位置的元素。

public synchronized E get(int index) {
		// 指定索引的合法性检查
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);

		// 返回数组中指定位置的元素
    return elementData(index);
}

40. public synchronized E set(int index, E element)

用指定的元素替换此Vector中指定位置的元素。

源码如下:

public synchronized E set(int index, E element) {
		// 指定索引的合法性检查
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);

		// 取出指定索引位置的原值
    E oldValue = elementData(index);
		// 将指定索引位置的元素替换为指定的元素
    elementData[index] = element;
		// 返回此索引位置的原值
    return oldValue;
}

41. public synchronized boolean add(E e)

将指定的元素附加到此Vector的末尾。

源码如下:

public synchronized boolean add(E e) {
		// 修改次数加1
    modCount++;
		// 确保容量足够
    ensureCapacityHelper(elementCount + 1);
		// 将数组的elementCount索引位置设置为指定元素e,然后将elementCount加1
    elementData[elementCount++] = e;
    return true;
}

42. public boolean remove(Object o)

移除此Vector中第一次出现的指定元素,如果Vector不包含该元素,则它保持不变。更正式地说,删除满足(o==null ? get(i)==null : o.equals(get(i)))的最低索引i的元素,(如果存在这样的元素)。

源码如下:

public boolean remove(Object o) {
    return removeElement(o);
}

43. public void add(int index, E element)

在此Vector的指定位置插入指定元素。将当前在该位置的元素(如果有)和任何后续元素向右移动(将它们的索引加一)。

源码如下:

public void add(int index, E element) {
    insertElementAt(element, index);
}

44. public synchronized E remove(int index)

移除此Vector中指定位置的元素。将任何后续元素向左移动(将它们的索引中减一)。返回从Vector中删除的元素。

源码如下:

public synchronized E remove(int index) {
		// 修改次数加1
    modCount++;
		// 指定索引的合法性校验
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);
		// 取出指定索引位置的原值
    E oldValue = elementData(index);

		// 需要移动索引位置的元素个数 = 指定索引及其后面的元素
    int numMoved = elementCount - index - 1;
		// 需要移动索引的元素个数大于0,则通过数组复制进行批量移动
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
		// 将元素个数减1,然后将元素个数位置的元素置为null,以使其可被垃圾回收
    elementData[--elementCount] = null; // Let gc do its work

		// 返回原值
    return oldValue;
}

45. public void clear()

从此Vector中删除所有元素。此调用返回后,Vector将为空(除非它引发异常)。

源码如下:

public void clear() {
    removeAllElements();
}

46. public synchronized boolean containsAll(Collection c)

如果此Vector包含指定Collection中的所有元素,则返回true

当指定的集合为空时,会抛出NullPointerException

源码如下:

public synchronized boolean containsAll(Collection<?> c) {
		// 调用AbstractCollection的containsAll进行判断
    return super.containsAll(c);
}

47. public synchronized boolean addAll(Collection<? extends E> c)

将指定Collection中的所有元素按照指定该集合的迭代器返回的顺序追加到此Vector的末尾。如果在操作进行时修改了指定的Collection,则此操作的行为将变得未知。 (这意味着如果指定的Collection是此Vector且此Vector非空,则此次调用的行为未知。)

如果此Vector由于调用而更改,则返回true

源码如下:

public synchronized boolean addAll(Collection<? extends E> c) {
		// 修改次数加1
    modCount++;
		// 将指定的集合转化为数组
    Object[] a = c.toArray();
		// 取出数组的长度
    int numNew = a.length;
		// 确保容量足够容纳下此数组
    ensureCapacityHelper(elementCount + numNew);
		// 将数组a复制到此Vector的最后一个元素后面
    System.arraycopy(a, 0, elementData, elementCount, numNew);
		// 增加元素个数
    elementCount += numNew;
		// 返回新增加的元素个数是否不为0,不为0说明有新元素添加到此Vector,返回true
    return numNew != 0;
}

48. public synchronized boolean removeAll(Collection c)

从此Vector中删除包含在指定Collection中的所有元素。

源码如下:

public synchronized boolean removeAll(Collection<?> c) {
		// 调用AbstractCollection的removeAll方法
    return super.removeAll(c);
}

49. public synchronized boolean retainAll(Collection c)

仅保留此Vector中包含在指定Collection中的元素。换句话说,从此Vector中删除所有未包含在指定Collection中的元素。

源码如下:

public synchronized boolean retainAll(Collection<?> c) {
		// 调用AbstractCollection的retainAll方法
    return super.retainAll(c);
}

50. public synchronized boolean addAll(int index, Collection<? extends E> c)

将指定Collection中的所有元素插入此Vector的指定位置。将当前在该位置的元素(如果有)和任何后续元素向右移动(增加它们的索引)。新元素将按照指定集合的迭代器返回的顺序出现在Vector中。

public synchronized boolean addAll(int index, Collection<? extends E> c) {
		// 增加修改次数
    modCount++;
		// 指定索引的合法性校验,大于等于0 且 小于等于元素个数
    if (index < 0 || index > elementCount)
        throw new ArrayIndexOutOfBoundsException(index);

		// 将指定集合转化为数组
    Object[] a = c.toArray();
		// 数组大小
    int numNew = a.length;
		// 确保此Vector的容量足够容纳下指定集合的所有元素
    ensureCapacityHelper(elementCount + numNew);

		// 需移动索引的元素个数
    int numMoved = elementCount - index;
		// 如果需移动索引的元素个数大于0,则执行数组复制,先往后移动这些元素
    if (numMoved > 0)
        System.arraycopy(elementData, index, elementData, index + numNew,
                         numMoved);

		// 将指定集合转化的数组复制到此Vector数据数组的指定位置
    System.arraycopy(a, 0, elementData, index, numNew);
		// 元素个数增加
    elementCount += numNew;
		// 返回是否新增了元素至此Vector
    return numNew != 0;
}

51. public synchronized boolean equals(Object o)

比较指定的Object与此Vector是否相等。当且仅当指定的Object也是一个List,两个List的大小相同,并且两个List中所有对应的元素对都相等时,才返回true。(如果(e1==null ? e2==null : e1.equals(e2)),说明两个元素e1e2相等。)换句话说, 如果两个List以相同的顺序包含相同的元素,则它们被定义为相等。

源码如下:

public synchronized boolean equals(Object o) {
		// 调用AbstractList的equals方法
    return super.equals(o);
}

52. public synchronized int hashCode()

返回此Vector的哈希编码值。

源码如下:

public synchronized int hashCode() {
		// 调用AbstractList的hashCode方法
    return super.hashCode();
}

53. public synchronized String toString()

返回此Vector的字符串表示形式,其中包含每个元素的字符串表示形式。

源码如下:

public synchronized String toString() {
		// 调用AbstractCollection的toString方法
    return super.toString();
}

54. public synchronized List<E> subList(int fromIndex, int toIndex)

返回此List中的fromIndex(包含)和toIndex(不包含)之间部分的视图。 (如果fromIndextoIndex相等,则返回的List为空。)返回的List基于此List,因此返回的List中的更改会反映在此List中,反之亦然。返回的List支持此List支持的所有可选List操作。

这种方法消除了对显式范围操作(数组通常存在的排序)的需要。通过对子列表视图而不是整个列表进行操作,任何需要列表的操作都可以用作范围操作。例如,以下惯用语法从List中删除一系列元素:list.subList(from, to).clear();,可以为indexOflastIndexOf构造类似的习惯用法,并且Collections类中的所有算法都可以应用于子列表。

如果基础列表(即此列表)以除了通过返回列表以外的任何方式进行了结构修改,则此方法返回的列表的语义将变得未知。 (结构修改是那些改变List的大小,或者以其他方式扰乱它,以致正在进行的迭代可能会产生不正确的结果。)

源码如下:

public synchronized List<E> subList(int fromIndex, int toIndex) {
		// 调用Collections中的方法获取一个同步的列表
    return Collections.synchronizedList(super.subList(fromIndex, toIndex),
                                        this);
}

55. protected synchronized void removeRange(int fromIndex, int toIndex)

从此列表中删除所有索引在fromIndex(含)和toIndex(不含)之间的所有元素。将所有后续元素向左移动(减小其索引)。此调用减小列表的(toIndex-fromIndex)个元素。 (如果toIndex == fromIndex,则此操作无效。)

源码如下:

protected synchronized void removeRange(int fromIndex, int toIndex) {
		// 增加修改次数
    modCount++;
		// 计算出需移动多少个元素
    int numMoved = elementCount - toIndex;
		// 将需移动的元素往前移动至fromIndex处
    System.arraycopy(elementData, toIndex, elementData, fromIndex,
                     numMoved);

    // Let gc do its work
		// 此时,Vector对象的元素个数未变,因为要被删除的范围内的元素已被其后的元素覆盖
		// 需要将移动前的索引位置的元素置为空,以促使垃圾回收
		// 例如:
		// 原Vector:[0, 1, 2, 3, 4],现在对其调用removeRange(1, 3)方法
		// 数组复制后:[0, 3, 4, 3, 4]
		// 最终:[0, 3, 4]
    int newElementCount = elementCount - (toIndex-fromIndex);
    while (elementCount != newElementCount)
        elementData[--elementCount] = null;
}

56. private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException

从流中加载Vector实例(即反序列化它)。此方法执行检查以确保字段的一致性。

源码如下:

private void readObject(ObjectInputStream in)
        throws IOException, ClassNotFoundException {
		// 从流中读取出字段信息
    ObjectInputStream.GetField gfields = in.readFields();
		// 取出elementCount字段的值
    int count = gfields.get("elementCount", 0);
		// 取出elementData字段的值
    Object[] data = (Object[])gfields.get("elementData", null);
		// 对取出字段的合理性做校验
		// 判断包括:count不能小于0 且 data不能为空 且count需与data的长度一致
    if (count < 0 || data == null || count > data.length) {
        throw new StreamCorruptedException("Inconsistent vector internals");
    }
		// 将流中的elementCount赋值给当前Vector的elementCount
    elementCount = count;
		// 将流中的elementData数组的拷贝赋值给当前Vector的elementData
    elementData = data.clone();
}

57. private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException

Vector实例的状态保存到流中(即序列化它)。该方法执行同步以保证序列化数据的一致性。

源码如下:

private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
    final java.io.ObjectOutputStream.PutField fields = s.putFields();
    final Object[] data;
    synchronized (this) {
				// 将capacityIncrement放入流
        fields.put("capacityIncrement", capacityIncrement);
				// 将elementCount放入流
        fields.put("elementCount", elementCount);
				// 执行对象数组的复制
        data = elementData.clone();
    }
		// 将对象数组的拷贝放入流
    fields.put("elementData", data);
		// 将上述设定写入流中
    s.writeFields();
}

58. public synchronized ListIterator<E> listIterator(int index)

返回在此列表元素上从指定位置开始的列表迭代器(以适当的顺序)。指定的索引指示初始调用next将返回的第一个元素。初次调用previous将返回指定索引减一的元素。

返回的列表迭代器是“快速失败”的。

源码如下:

public synchronized ListIterator<E> listIterator(int index) {
		// 指定索引的合理性校验
    if (index < 0 || index > elementCount)
        throw new IndexOutOfBoundsException("Index: "+index);
		// 返回一个ListItr实例
    return new ListItr(index);
}

59. public synchronized ListIterator<E> listIterator()

返回此列表中的元素的列表迭代器(按适当顺序)。

返回的列表迭代器是“快速失败”的。

源码如下:

public synchronized ListIterator<E> listIterator() {
		// 返回一个从索引位置0处开始的列表迭代器实例
    return new ListItr(0);
}

60. public synchronized Iterator<E> iterator()

返回在此列表中元素上的迭代器(以正确的顺序)。

返回的迭代器是“快速失败”的。

源码如下:

public synchronized Iterator<E> iterator() {
		// 返回一个Itr实例
    return new Itr();
}

61. private class Itr implements Iterator<E>

AbstractList.Itr的优化版本。

61.1 int cursor;

要返回的下一个元素的索引,也即“游标“。

61.2 int lastRet = -1;

返回的最后一个元素的索引,如果还没有返回过元素,则是-1

61.3 int expectedModCount = modCount;

期望更新次数,默认值取当前Vector的修改次数。

61.4 public boolean hasNext()

判断是否还有下一个元素可返回,若有,则返回true

源码如下:

public boolean hasNext() {
    // Racy but within spec, since modifications are checked
    // within or after synchronization in next/previous
		// 返回当前游标是否处于elementCount索引位置
    return cursor != elementCount;
}

61.5 public E next()

获取下一个元素。

源码如下:

public E next() {
    synchronized (Vector.this) {
				// 检查是否有修改
        checkForComodification();
        int i = cursor;
				// 如果当前游标大于等于元素个数,则抛出无此元素异常
        if (i >= elementCount)
            throw new NoSuchElementException();
				// 游标后移一位(即加1)
        cursor = i + 1;
				// 将移动前的原游标位置赋值给最后返回的索引字段,然后取出该位置的元素返回
        return elementData(lastRet = i);
    }
}

61.6 public void remove()

删除当前迭代器最近一次返回的元素。

源码如下:

public void remove() {
		// 如果最后返回索引字段的值为-1,说明要么还未调用next获取过元素,要么已经删除过该元素
    if (lastRet == -1)
        throw new IllegalStateException();
    synchronized (Vector.this) {
        checkForComodification();
				// 调用Vector的remove方法删除最后返回索引位置的元素
        Vector.this.remove(lastRet);
				// 更新期望更新次数
        expectedModCount = modCount;
    }
		// 当前游标置于最近一次返回的索引处
    cursor = lastRet;
		// 最近返回的索引字段的值置为-1
    lastRet = -1;
}

61.7 public void forEachRemaining(Consumer<? super E> action)

对迭代器尚未遍历到的元素执行给定的操作。

源码如下:

@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")
				// 取出当前Vector存放数据的数组
        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();
    }
}

61.8 final void checkForComodification()

检查是否存在并发修改。

源码如下:

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

62. final class ListItr extends Itr implements ListIterator<E>

AbstractList.ListItr的优化版本。

62.1 ListItr(int index)

构建一个ListItr

源码如下:

ListItr(int index) {
    super();
    cursor = index;
}

62.2 public boolean hasPrevious()

判断前面是否还有元素可返回,若有,则返回true

源码如下:

public boolean hasPrevious() {
		// 若当前游标不在索引位置0处,说明前面还有元素可返回
    return cursor != 0;
}

62.3 public int nextIndex()

返回下一个元素的索引。

源码如下:

public int nextIndex() {
		// 即返回游标位置
    return cursor;
}

62.4 public int previousIndex()

返回上一个元素的索引。

源码如下:

public int previousIndex() {
		// 返回当前游标位置减1
    return cursor - 1;
}

62.5 public E previous()

返回上一个元素。

源码如下:

public E previous() {
    synchronized (Vector.this) {
        checkForComodification();
				// 取出前面一个元素的索引位置
        int i = cursor - 1;
				// 如果得到的索引位置小于0,则说明前面没有元素了,此时抛出异常
        if (i < 0)
            throw new NoSuchElementException();
				// 将得到的索引位置赋值给游标
        cursor = i;
				// 将得到的索引位置赋值给最近一次返回的元素索引字段,然后返回该位置的元素
        return elementData(lastRet = i);
    }
}

62.6 public void set(E e)

替换掉最近一次返回的元素。

源码如下:

public void set(E e) {
		// 如果最近返回的元素索引位置为-1,说明此时没有最近一次返回的元素(也可能已被删除),则此时抛出异常
    if (lastRet == -1)
        throw new IllegalStateException();
    synchronized (Vector.this) {
        checkForComodification();
				// 调用Vector的set方法 替换最近一次返回的元素为指定的元素
        Vector.this.set(lastRet, e);
    }
}

62.7 public void add(E e)

在最近一次返回的元素后面添加参数中指定的元素。

源码如下:

public void add(E e) {
    int i = cursor;
    synchronized (Vector.this) {
        checkForComodification();
				// 在当前游标位置插入指定的元素e
        Vector.this.add(i, e);
				// 更新期望更新次数
        expectedModCount = modCount;
    }
		// 游标后移一位
    cursor = i + 1;
		// 最近返回的元素索引置为-1
    lastRet = -1;
}

63. public synchronized void forEach(Consumer<? super E> action)

对当前Vector实例的每个元素执行给定的动作。

源码如下:

@Override
public synchronized void forEach(Consumer<? super E> action) {
    Objects.requireNonNull(action);
    final int expectedModCount = modCount;
    @SuppressWarnings("unchecked")
    final E[] elementData = (E[]) this.elementData;
    final int elementCount = this.elementCount;
    // 遍历当前Vector的对象数组
    for (int i=0; modCount == expectedModCount && i < elementCount; i++) {
        // 对每个元素执行给定动作
        action.accept(elementData[i]);
    }
    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }
}

64. public synchronized boolean removeIf(Predicate<? super E> filter)

删除当前Vector实例中满足给定条件的元素。

源码如下:

@Override
@SuppressWarnings("unchecked")
public synchronized boolean removeIf(Predicate<? super E> filter) {
    Objects.requireNonNull(filter);
    // 先找出要被删除的元素
    // figure out which elements are to be removed
    // 判断过程中抛出了任何异常,都不会导致此集合改变
    // any exception thrown from the filter predicate at this stage
    // will leave the collection unmodified
    int removeCount = 0;
    final int size = elementCount;
    // 创建一个BitSet实例,用于记录要被删除记录的索引
    final BitSet removeSet = new BitSet(size);
    final int expectedModCount = modCount;
    // 遍历当前Vector的对象数组
    for (int i=0; modCount == expectedModCount && i < size; i++) {
        @SuppressWarnings("unchecked")
        // 取出当前位置的元素
        final E element = (E) elementData[i];
        // 对当前位置的元素执行给定的条件判断
        if (filter.test(element)) {
            // 如果判断的结果为true,则记录当前索引
            removeSet.set(i);
            removeCount++;
        }
    }
    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }

    // shift surviving elements left over the spaces left by removed elements
    // 将未删除的元素向左移
    final boolean anyToRemove = removeCount > 0;
    if (anyToRemove) {
        // 计算出剩余后的元素个数
        final int newSize = size - removeCount;
        // 遍历对象数组,i代表了原数组索引,j代表新数组索引
        for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
            // 取出i及以后的第一个未被删除的元素的索引
            i = removeSet.nextClearBit(i);
            // 将该未被删除的元素放置到j位置
            elementData[j] = elementData[i];
        }
        // 遍历新对象数组(指完成元素移动后的数组),将后部的元素置为null
        for (int k=newSize; k < size; k++) {
            elementData[k] = null;  // Let gc do its work
        }
        elementCount = newSize;
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }

    return anyToRemove;
}

65. public synchronized void replaceAll(UnaryOperator<E> operator)

对每个元素执行给定的操作,并用得到的返回值替换该元素。

源码如下:

@Override
@SuppressWarnings("unchecked")
public synchronized void replaceAll(UnaryOperator<E> operator) {
    Objects.requireNonNull(operator);
    final int expectedModCount = modCount;
    final int size = elementCount;
    // 遍历对象数组
    for (int i=0; modCount == expectedModCount && i < size; i++) {
        // 对当前元素执行给定的操作,用计算出的结果替换当前元素
        elementData[i] = operator.apply((E) elementData[i]);
    }
    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }
    modCount++;
}

66. public synchronized void sort(Comparator<? super E> c)

使用给定的比较器对当前Vector进行排序。

源码如下:

@SuppressWarnings("unchecked")
@Override
public synchronized void sort(Comparator<? super E> c) {
    final int expectedModCount = modCount;
    // 使用Arrays.sort方法对对象数组进行排序
    Arrays.sort((E[]) elementData, 0, elementCount, c);
    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }
    modCount++;
}

67. public Spliterator<E> spliterator()

在此列表的元素上创建一个“延迟绑定”、“快速失败”的拆分器。

该拆分器报告的特征有:Spliterator#SIZEDSpliterator#SUBSIZEDSpliterator#ORDERED。覆盖该实现时应该记录附加的特征值的报告。

源码如下:

@Override
public Spliterator<E> spliterator() {
    // 返回一个VectorSpliterator实例
    return new VectorSpliterator<>(this, null, 0, -1, 0);
}

68. static final class VectorSpliterator<E> implements Spliterator<E>

Vector的拆分器,类似于ArrayList的拆分器。

68.1 private final Vector<E> list;

当前拆分器所持有的Vector实例。

68.2 private Object[] array;

当前拆分器所持有的Vector实例(即上面的list)的元素数据数组(elementData)。

68.3 private int index;

当前索引,在前进和拆分时修改。

68.4 private int fence;

在使用前一直为-1;然后是从1到最后一个索引。

68.5 private int expectedModCount;

设置围栏(fence)时初始化该值。

68.6 VectorSpliterator(Vector<E> list, Object[] array, int origin, int fence, int expectedModCount)

创建覆盖给定范围的新拆分器,也是当前拆分器类的唯一构造函数。

源码如下:

VectorSpliterator(Vector<E> list, Object[] array, int origin, int fence,
                  int expectedModCount) {
    this.list = list;
    this.array = array;
    this.index = origin;
    this.fence = fence;
    this.expectedModCount = expectedModCount;
}

68.7 private int getFence()

首次使用时初始化围栏的值。

源码如下:

private int getFence() { // initialize on first use
    int hi;
    // 围栏小于0才执行初始化,否则直接返回当前的围栏值
    if ((hi = fence) < 0) {
        synchronized(list) {
            // 初始化array属性,将其值置为列表的元素数据数组
            array = list.elementData;
            // 期望修改次数置为列表的修改次数
            expectedModCount = list.modCount;
            // 将围栏设置为列表的元素个数
            hi = fence = list.elementCount;
        }
    }
    return hi;
}

68.8 public Spliterator<E> trySplit()

执行拆分。

源码如下:

public Spliterator<E> trySplit() {
    // 获取围栏位置、当前索引位置,然后基于这俩计算出从当前索引至围栏位置的中间位置
    int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
    // 只有当当前索引小于上面计算出的中间位置时拆分才有意义,所以,不满足时不会进行拆分
    return (lo >= mid) ? null :
        // 如果需要拆分时,创建一个新的VectorSpliterator实例,其范围为当前索引至中间位置
        // 同时index = mid这一步,将当前拆分器的当前索引位置推后至中间位置
        // 至此,完成拆分
        new VectorSpliterator<E>(list, array, lo, index = mid,
                                 expectedModCount);
}

68.9 public boolean tryAdvance(Consumer<? super E> action)

对当前索引位置的元素执行给定的操作,然后将当前索引右移一位(即加一)。

源码如下:

@SuppressWarnings("unchecked")
public boolean tryAdvance(Consumer<? super E> action) {
    int i;
    if (action == null)
        throw new NullPointerException();
    // 当前索引不可大于等于围栏位置
    if (getFence() > (i = index)) {
        // 上面已经取出了当前索引的位置,赋值给了i,此处对当前索引进行右移操作,即加一
        index = i + 1;
        // 对i位置的元素执行给定的操作
        action.accept((E)array[i]);
        if (list.modCount != expectedModCount)
            throw new ConcurrentModificationException();
        return true;
    }
    return false;
}

68.10 public void forEachRemaining(Consumer<? super E> action)

对当前拆分器的剩余元素依次执行给的操作。

源码如下:

@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> action) {
    int i, hi; // hoist accesses and checks from loop
    Vector<E> lst; Object[] a;
    if (action == null)
        throw new NullPointerException();
    // list不可为空
    if ((lst = list) != null) {
        // 如果围栏小于0,则重新获取围栏
        if ((hi = fence) < 0) {
            synchronized(lst) {
                expectedModCount = lst.modCount;
                a = array = lst.elementData;
                hi = fence = lst.elementCount;
            }
        }
        else
            a = array;
        // 如果数组不为空 且 当前索引大于等于0 且 围栏位置小于等于数组长度,则遍历数组
        // 此处有个隐秘操作:index = hi,这一步将当前索引位置推至围栏位置,这样就不用每遍历到一个元素就对index进行加1了
        if (a != null && (i = index) >= 0 && (index = hi) <= a.length) {
            // 遍历数组,从当前索引位置到围栏位置
            while (i < hi)
                // 依次执行给定操作
                action.accept((E) a[i++]);
            if (lst.modCount == expectedModCount)
                return;
        }
    }
    throw new ConcurrentModificationException();
}

68.11 public long estimateSize()

获取剩余元素的预估个数。

源码如下:

public long estimateSize() {
    // 围栏位置减去当前索引位置
    return (long) (getFence() - index);
}

68.12 public int characteristics()

获取当前拆分器报告的特征值。

源码如下:

public int characteristics() {
    return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}