文章目录
前言
本文章将分析Vector集合的源码和常用方法实现。
一、Vector
1.1特点
- 集合中方法都加了synchronized关键字修饰,所以其线程安全
- Vector可以指定增长因子,如果该增长因子指定了,那么扩容的时候会每次新的数组大小会在原数组的大小基础上加上增长因子;如果不指定增长因子,那么就给原数组大小*2
1.2实现(继承)了哪些接口(类)
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
根据源码所示:
- Vector 继承了AbstractList,实现了List接口。
- Vector实现了RandmoAccess接口,即提供了随机访问功能。
- Vector 实现了Cloneable接口,即实现克隆功能。
- Vector 实现Serializable接口,表示支持序列化。
二、常用方法
2.1构造方法
2.1.1Vector()
//调用了有参构造方法Vector(int initialCapacity)
public Vector() {
this(10);
}
2.1.2Vector(int initialCapacity)
//调用了Vector(int initialCapacity,int capacityIncrement)
//增长因子为0
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
2.1.3Vector(int initialCapacity,int capacityIncrement)
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//初始化数组容量,根据传入的initialCapacity设定容量大小
this.elementData = new Object[initialCapacity];
//根据capacityIncrement初始化增长因子大小
this.capacityIncrement = capacityIncrement;
}
2.1.4public Vector(Collection<? extends E> c)
public Vector(Collection<? extends E> c) {
//将c集合转换成数组
elementData = c.toArray();
//获取数组长度
elementCount = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
//如果不是同一个类型,则通过Arrays.copyOf复到elementData
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}
2.2 add(E e)
public synchronized boolean add(E e) {
//记录操作次数
modCount++;
//判断容量大小,若容量足够则直接添加,否则扩容
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
此方法在Vector尾部追加元素
2.3 add(int index,E element)
public void add(int index, E element) {
insertElementAt(element, index);
}
public synchronized void insertElementAt(E obj, int index) {
modCount++;
//判断index是否合法
if (index > elementCount) {
throw new ArrayIndexOutOfBoundsException(index
+ " > " + elementCount);
}
//判断容量大小
ensureCapacityHelper(elementCount + 1);
//数组拷贝,将index到末尾的元素拷贝到index +1 到末尾的位置,将index位置流出来
System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
elementData[index] = obj;
elementCount++;
}
此方法在Vector尾部追加元素
2.4扩容方法
2.4.1ensureCapacityHelper(int minCapacity),grow(int minCapacity)
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void ensureCapacityHelper(int minCapacity) {
// 判断是否需要扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// 获得elementData初始容量
int oldCapacity = elementData.length;
//判断扩容因子是否大于0,如果大于0,那就扩充扩容因子的数量,否则加上初始容量也就是翻倍
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
//如果扩容后还不够,则新容量改为实际需要的minCapacity容量大小
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果新数组长度比MAX_ARRAY_SIZE还要大,则使用hugeCapacity(minCapacity)
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//按照新的容量newCapacity创建一个新数组,然后将内容复制到新数组中
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
//溢出抛异常
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
//如果最小容量大于MAX_ARRAY_SIZE,则容量设置为Integer.MAX_VALUE,否则设置为MAX_ARRAY_SIZE
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
2.5remove(Object o)
删除指定元素
public boolean remove(Object o) {
return removeElement(o);
}
实际上是使用了removeElement方法
public synchronized boolean removeElement(Object obj) {
modCount++;
//取得指定元素下标
int i = indexOf(obj);
if (i >= 0) {
//使用removeElementAt方法
removeElementAt(i);
return true;
}
return false;
}
public synchronized void removeElementAt(int index) {
modCount++;
//判断index是否合法
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
else if (index < 0) {
throw new ArrayIndexOutOfBoundsException(index);
}
//要移动的元素个数
int j = elementCount - index - 1;
if (j > 0) {
//将index之后的元素向前移动一位
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}
2.6remove(int index)
public synchronized E remove(int index) {
modCount++;
//判断index是否合法
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;
}
2.7setElementAt(E obj ,int index)
public synchronized void setElementAt(E obj, int index) {
//判断index是否合法
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
//将elementData数组中指定位置替换为obj
elementData[index] = obj;
}
2.8get(int index)
public synchronized E get(int index) {
//判断index是否合法
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
//返回elementData数组中index位置的元素
return elementData(index);
}
三、Vector与ArrayList的区别
看完源码我们可以发现Vector与ArrayList十分相似,他们底层都是用数组实现存储,查找修改都很方便,但是不利于删除。
- Vector是线程安全的,而ArrayList线程不安全。
- Vector可以指定扩容因子,根据扩容因子扩容内部数组,而
ArrayList内部则是采用1.5倍扩容(实际上是位运算len = len + len>>2)
总结
以上就是本文章的内容,本文章介绍了Vector集合的源码以及特点,扩容的机制。