Vector
继承关系
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
从继承关系可以看出
Vector继承于AbstractList,实现了List、RandomAccess、Cloneable、 Serializable等接口。
1.Vector 继承了AbstractList,实现了List接口。
2.Vector实现了RandmoAccess接口,即提供了随机访问功能。
3.Vector 实现了Cloneable接口,即实现克隆功能。
4.Vector 实现Serializable接口,支持序列化。
构造方法和初始化
底层是动态数组实现的
protected Object[] elementData;//数组
protected int elementCount;//放入数组的元素个数
protected int capacityIncrement;//增长系数
四个构造方法
1.传入初始大小和增长系数的构造方法
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
2.指定初始容量和的空向量,其增长系数为0
/**
* Constructs an empty vector with the specified initial capacity and
* with its capacity increment equal to zero.
* 指定初始容量和的空向量,其容量增量为零
*/
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
3.构造一个空向量,使其内部数据数组的大小为10,其标准容量增量为0
/**
* Constructs an empty vector so that its internal data array
* has size {@code 10} and its standard capacity increment is
* zero.
*构造一个空向量,使其内部数据数组的大小为{@code 10},其标准容量增量为0
*/
public Vector() {
this(10);
}
4.传入一个集合构造器,并返回一个顺序的Vector
/**
* Constructs a vector containing the elements of the specified
* collection, in the order they are returned by the collections iterator.
* 构造包含指定元素的向量集合,按照集合返回的顺序迭代器
*/
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)//判断c.toArray是否是Object[]类型
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);//复制数组构成Vector
}
初始化
public Vector() {
this(10);
}
可以看出默认长度是10个。
常见api
添加
同ArrayList类似也是经历两个步骤:
1.增加数组长度,
2.将元素添加到数组中
只是增加了锁synchronized,保证线程安全。
public synchronized void addElement(E obj) {//加锁保证线程安全
modCount++;//记录修改次数
ensureCapacityHelper(elementCount + 1);//增加数组长度(涉及扩容)
elementData[elementCount++] = obj;//添加元素
}
删除
删除分为两种:
1.根据元素删除
根据元素删除的原理:先找到对应元素的下标,再根据下标删除
2.根据下标删除
根据元素的删除
//根据元素删除
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) {
//arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
//从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。
//第一个elementData:原数组
//第二个elementData:目标数组
//源数组中位置在 srcPos 到 srcPos+length-1 之间的组件被
//分别复制到目标数组中的 destPos 到 destPos+length-1 位置。
//public static void arraycopy(Object src,int srcPos,Object dest,int destPos, int length)
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--;
//此时最后的一个元素设为nul,这是数组的长度就减1了
elementData[elementCount] = null; /* to let gc do its work */
}
移除所有元素
循环置为null
public synchronized void removeAllElements() {
modCount++;
// Let gc do its work
for (int i = 0; i < elementCount; i++)
elementData[i] = null;
elementCount = 0;
}
romove方法
底层还是调用的removeElement方法
public boolean remove(Object o) {
return removeElement(o);
}
查询
返回对应下标的数据
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
return elementData(index);
}
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
指定下标下设置值
public synchronized E set(int index, E element) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
克隆
就是创建一个新数组,将老元素复制到新的数组中,返回该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(e);
}
}
扩容
扩充容量
//扩充容量
public synchronized void ensureCapacity(int minCapacity) {
if (minCapacity > 0) {
modCount++;
ensureCapacityHelper(minCapacity);
}
}
扩充容量帮助函数
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
真正的扩容方法
//最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
//扩充容量执行方法
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// 根据capacityIncrement进行判断,capacityIncrement> 0
//增加capacityIncrement个容量,否则容量扩充当前容量的一倍
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//扩容操作,生成已给新的数组,容量为newCapacity,并将elementData中的元素全部拷贝到新数组中,
//并将新生成的数组在赋值给elementData
elementData = Arrays.copyOf(elementData, newCapacity);
}
MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8 的原因:
数组作为一个对象,需要一定的内存存储对象头信息,对象头信息最大占用内存不可超过8字节 最大的容量长度
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
小结
1.Vector 可以存放null;
2.Vector线程安全;
3.Vector内部实际上是一个Object的数组;
4.Vector每次扩容是2倍;
5.Vector本质是一个数组所以查询很快,新增和删除要慢些;
6.和ArrayList类似Vector底层数组存/取元素效率非常的高(get/set),查找,时间复杂度是O(1),插入和删除元素效率时间复杂度为O(n)。
Vector 和ArrayList的区别
1.Vector线程安全,ArrayList线程不安全;
2.它们都是动态扩容的,但是Vector扩容为2倍,ArrayList扩容1.5倍;
3.ArrayList由于不需要同步,性能优于Vector。
总结
Vector 和 ArrayList 还有 LinkedList都是同一级的,它们中插入最快的是LinkedList,
因为插入数据时只需要记录当前项的前后项即可,而其他两个平均情况下需要遍历向后移动。
写在后面的话
你是守宫砂,也是明月光,世事繁复,愿你心境四季如春!