Vector
Vector
简述
核心内容
- 数据结构。
- 初始化)。
- 添加元素。
- 移除元素。
- 查找。
- 扩容(含自动扩容)。
Vector 简介
Vector JDK1.0 开始支持的。
Vector 和 Arraylist 类型,但是是线程安全的,这里着重关注下不同的点,相似的功能参考Arraylist 源码分析。
详述
Vector 类图
略,同 ArrayList。
数据结构和核心方法
public class Vector<E> ...{
/** 保存 Vector 数据的数组,和 ArrayList 对比,没有 transient */
protected Object[] elementData;
/** Vector 中实际数据的数量,ArrayList 的属性为 size */
private int elementCount;
/** 扩容因子(容量增长系数),ArrayList 无该字段 */
protected int capacityIncrement;
public boolean add(E e)...
public boolean addAll(Collection<? extends E> c)...
public E set(int index, E element)...
public E get(int index)...
public E remove(int index)...
public void trimToSize()...
}
数据结构同 ArrayList,内容不再冗余说明。
TIP
Vector 中 elementData 为什么没有被 transient 修饰?
估摸是历史原因,Vector 的 JDK1.0 版本的,ArrayList 是 JDK1.2 版本的,因此 ArrayList 对此做了点优化。
初始化
Vector 提供了四种方式的构造器。
/** Vector 带容量大小的构造函数。*/
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//新建一个数组,数组容量是 initialCapacity
this.elementData = new Object[initialCapacity];
//设置增长容量增长系数
this.capacityIncrement = capacityIncrement;
}
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
public Vector() {
this(10);
}
/** Vector 带容量大小的构造函数 */
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);
}
TIP
Vector 中默认的初始化容量是 10,通过跟踪调试源码发现,public Vector()...
默认已经分配好了 10 长度的空间。
添加元素-add
TIP
- 对比 ArrayList,大部分方法上加了 synchronized 关键字处理。
- 其他的一些细节,看注释描述。
/** 添加一个元素,直接添加到数组末尾 */
public synchronized boolean add(E e) {
modCount++; // 多了这个,是因为有的方法没有加 synchronized
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
/** 在指定索引添加一个元素 */
public void add(int index, E element) {
insertElementAt(element, index);
}
/** 在指定索引添加一个元素 */
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++;
}
添加元素-addAll
/** 在末尾索引处开始添加集合的所有元素 */
public synchronized boolean addAll(Collection<? extends E> c) {
modCount++;
Object[] a = c.toArray();
int numNew = a.length;
// 在这里会做方法扩容处理
ensureCapacityHelper(elementCount + numNew);
// 添加元素
System.arraycopy(a, 0, elementData, elementCount, numNew);
elementCount += numNew;
return numNew != 0;
}
/** 在指定索引处开始添加集合的所有元素 */
public synchronized boolean addAll(int index, Collection<? extends E> c) {
modCount++;
if (index < 0 || index > elementCount)
throw new ArrayIndexOutOfBoundsException(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityHelper(elementCount + numNew);
int numMoved = elementCount - index;
if (numMoved > 0)
// index 的元素移动从 c.size 长度
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
// 复制要添加的元素
System.arraycopy(a, 0, elementData, index, numNew);
elementCount += numNew;
return numNew != 0;
}
移除元素-remove
/** 移除指定索引上的元素
* 删除操作是 add() 操作的逆过程,需要将删除点之后的元素向前移动一个位置。需要注意的是为了让 GC 起作用,必须显式的为最后一个位置赋 null 值
*/
public synchronized E remove(int index) {
modCount++;
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
int numMoved = elementCount - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--elementCount] = null; // Let gc do its work
return oldValue;
}
/** 移除指定的元素 */
public boolean remove(Object o) {
return removeElement(o);
}
public synchronized boolean removeElement(Object obj) {
modCount++;
int i = indexOf(obj);
if (i >= 0) {
removeElementAt(i);
return true;
}
return false;
}
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 */
}
查找元素-get
/** 查找元素 */
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}
扩容(含自动扩容)
扩容和 ArrayList 不同,代码如下:
/** 扩容方法入口 */
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);
}
其他方法-trimToSize
/** 将底层数组的容量调整为当前列表保存的实际元素的大小 */
public synchronized void trimToSize() {
modCount++;
int oldCapacity = elementData.length;
if (elementCount < oldCapacity) {
elementData = Arrays.copyOf(elementData, elementCount);
}
}
其他方法-indexOf、lastIndexOf
/** 获取元素的第一次出现的 index */
public int indexOf(Object o) {
return indexOf(o, 0);
}
/** 获取元素从 index 索引开始,第一次出现的索引,ArrayList 没有该方法 */
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;
}
/** 获取元素的最后一次出现的 index */
public synchronized int lastIndexOf(Object o) {
return lastIndexOf(o, elementCount-1);
}
/** 获取元素从 index 索引结尾,最后一次出现的索引,ArrayList 没有该方法 */
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;
}
其他方法-toArray
public synchronized Object[] toArray() {
return Arrays.copyOf(elementData, elementCount);
}
总结
TIP
- 除线程安全外,其他基本同 ArrayList。
- Vector 的方法里面保留了 modCount++ 等 fail-fast 机制的内容。