![8e4537ba7019aa08daae26356fc91608.png](https://i-blog.csdnimg.cn/blog_migrate/d026d1fe39e08d2e7cfb626b920cd8cc.png)
前言
老规矩,先把官方注释完整的放出来。
/**
* 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.
*
* <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.
*
* <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>
*
* <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">
* 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}.
其实这里面的注释内容有关于快速失败和迭代器的部分跟LinkedList和ArrayList是一模一样的,我挑选一些Vector的特性把重点翻译一下。
Vector类实现了一个 可增长(growable)的数组对象,类似数组,它包含可以使用整数索引访问的组件。但是,在Vector创建之后,它的大小可以根据需要增长或缩小,以适应添加和删除等操作。
每个Vector都会试着通过维持 capacity(容量)和 capacityIncrement(扩容因子)来优化存储管理。
capacity(容量)总是至少和Vector的大小一样大,而它通常会更大一些,因为当成员被添加到Vector中时,Vector的存储量会成 块(chunks)增加,即capacityIncrement(扩容因子)的大小。
应用程序可以在插入大量成员之前增加Vector的容量;这减少了增量重新分配的代价。
源码
- 继承和实现
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
Vector继承AbstractList抽象父类,实现了List接口(规定了List的操作规范)、RandomAccess(可随机访问)、Cloneable(可拷贝)、Serializable(可序列化)
(这话在ArrayList里面说过)
2. 变量
/**
* 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;
/**
* 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;
/**
* 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;
Object[] elementData,这个就是Vector的本来面目了,朴实无华。
3.构造方法
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
public Vector() {
this(10);
}
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);
}
两个参数分别是初始容量和扩容因子,初始容量默认是10,扩容因子默认为0。
入参为collection时,将其转化为数组。
4.扩容方法
对于ArrayList和vector这种对象数组来说,扩容操作都是开辟一块新的位置,然后将原先的数据复制过来。只不过vector多了一个“扩容因子”概念的存在。
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;
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;
}
在Vector执行插入操作时,调用ensureCapacityHelper,传入的minCapacity为“elementCount + 1”,意味着默认扩容就是当前的大小加一。
然后判断如果扩容因子如果大于0,那么新的容量newCapacity的大小就是旧的容量oldCapacity加上扩容因子,否则新的容量就是oldCapacity×2.
然后当新的容量大于数组所能容纳的最大容量时,调用hugeCapacity
方法来计算,逻辑就是这个三目运算符
(minCapacity > MAX_ARRAY_SIZE)? Integer.MAX_VALUE : MAX_ARRAY_SIZE
MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
Integer.MAX_VALUE = 2147483647;
和ArrayList一样,hugeCapacity为啥子会需要判断minCapacity <0呢?
假如列表中已经有-1个元素,在添加新元素的时候,minCapacity 为原来的长度 + 1,溢出变为 minCapacity = -
-1,新的长度扩大到 1.5 倍也溢出为负数(绝对值 < minCapacity),此时
grow
方法中 新的长度 - 旧的长度 > 0(绝对值小的负数 - 绝对值大的负数),最后调用该方法时传递的 minCapacity 就是--1,将抛出异常。
最后如果 minCapacity 大于 ArrayList 能容纳的最大长度,就返回整型最大值,否则返回MAX_ARRAY_SIZE
(这话在ArrayList介绍的时候也说过)哈哈哈哈我就复制粘贴一下
至于为什么加一会变负数,那就又牵扯到二进制存储的事儿了。大家可以搜索一下java中的Byte 127 加一等于多少?
5.线程同步
这里面总重要问题就是,Vector是以什么方式来保证线程安全呢??
synchronized
就这一个秘诀。
在面试的时候Vector和ArrayList经常被拿来提问,除了线程安全的区别之外,也可以说一说扩容因子对于容量扩容时候的影响。
今天的文章到这里结束,我们下一章节介绍CopyOnWriteArrayList<E>。