Java Vector源码详解
Vector<E>源码详解(基于jdk1.8.0_162)
说明:Vector<E>底层使用了数组的方式实现,是一个线程安全的集合。
该章只列举了常用的增删查改方法,其它可以参考JDK文档。
Stack<E>:栈的特性是“先进后出”,继承了Vector<E>类,实现的功能。
相当于栈的底层也是数组实现,也是一个线程安全的对象。
一)类图:
Vector<E>继承了AbstractList<E>抽象类,实现了add、remove、set等功能。
Vector<E>继承了List<E>接口,依赖与Iterator<E>和ListIterator<E>接口,实现了数据迭代等功能。
Vector<E>是一个线程安全的集合。
备注:如需自己实现Vector类似的功能,可以继承AbstractList<E>抽象类,然后再自定义方法。
二)构造方法
1、Vector<E> vector = new Vector<E>();
构造一个容量默认为10、增量为0的空集合,当元素大小超出容量时,按(容量+容量)成倍的方式扩容。
2、Vector<E> vector = new Vector<E>(20);
构造一个指定容量为20、增量为0的空集合,当元素大小超出容量时,按(容量+容量)成倍的方式扩容。
3、Vector<E> vector = new Vector<E>(30,15);
构造一个指定容量为30、增量为15的空集合,当元素大小超出容量时,按(容量+增量)的方式扩容。
4、Vector<E> vector = new Vector<E>(Collection<? extends E> c);
构造一个包含指定元素集合的列表。
// 构造一个容量默认为10、增量为0的空集合,当元素大小超出容量时,按(容量+容量)成倍的方式扩容
public Vector() {
this(10);
}
// 构造一个指定容量为20、增量为0的空集合,当元素大小超出容量时,按(容量+容量)成倍的方式扩容
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
// 构造一个指定容量为30、增量为15的空集合,当元素大小超出容量时,按(容量+增量)的方式扩容
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(Collection<? extends E> c) {
elementData = c.toArray(); //把集合转换成一个Object[]数组
elementCount = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class) // 符合条件,复制成一个新数组再赋值
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}
三)添加
1、add(E e),一次添加一个元素,相当于在末尾添加,有返回值
addElement(E obj),一次添加一个元素,相当于在末尾添加,无返回值
public synchronized boolean add(E e) { // synchronized保证线程安全
modCount++;
ensureCapacityHelper(elementCount + 1); // 调用扩容方法
elementData[elementCount++] = e; // 添加元素
return true;
}
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
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; // 获取当前容器大小
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); // 根据新容器大小,返回一个数组
}
2、add(int index, E element),在指定的下标位置添加元素
public void add(int index, E element) {
insertElementAt(element, index);
}
public synchronized void insertElementAt(E obj, int index) {
modCount++;
if (index > elementCount) { // 判断index的有效性
throw new ArrayIndexOutOfBoundsException(index
+ " > " + elementCount);
}
ensureCapacityHelper(elementCount + 1); // 扩容方法
System.arraycopy(elementData, index, elementData, index + 1, elementCount - index); // 新数组
elementData[index] = obj; // 赋值
elementCount++;
}
3、addAll(Collection<? extends E> c),将一个集合添加到Vector中
public synchronized boolean addAll(Collection<? extends E> c) { // 线程安全
modCount++;
Object[] a = c.toArray(); // 转换成Object[]数组
int numNew = a.length;
ensureCapacityHelper(elementCount + numNew); // 扩容方法
System.arraycopy(a, 0, elementData, elementCount, numNew); // 新数组
elementCount += numNew; // 累计元素个数
return numNew != 0;
}
4、addAll(int index, Collection<? extends E> c),在指定下标位置,把该集合添加进去
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)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
System.arraycopy(a, 0, elementData, index, numNew); // 新数组
elementCount += numNew; // 累计元素个数
return numNew != 0;
}
各种添加方式性能比较
// add(E e)
public static void addE() {
long begin = System.currentTimeMillis();
Vector<Integer> intList = new Vector<Integer>();
for(int i=0; i<10000000; i++) {
intList.add(i);
}
long end = System.currentTimeMillis();
System.out.println("结果:add(E e)添加方式插入1000w个数,大概总耗时" + (end-begin) +"ms");
// 结果:add(E e)添加方式插入1000w个数,大概总耗时3363ms
}
// addElement(E e)
public static void addElement() {
long begin = System.currentTimeMillis();
Vector<Integer> intList = new Vector<Integer>();
for(int i=0; i<10000000; i++) {
intList.addElement(i);
}
long end = System.currentTimeMillis();
System.out.println("结果:addElement(E e)添加方式插入1000w个数,大概总耗时" + (end-begin) +"ms");
// 结果:addElement(E e)添加方式插入1000w个数,大概总耗时3353ms
}
// add(int index, E element)
public static void addIndexElement() {
long begin = System.currentTimeMillis();
Vector<Integer> intList = new Vector<Integer>();
for(int i=0; i<10000000; i++) {
intList.add(i, 666);
}
long end = System.currentTimeMillis();
System.out.println("结果:add(int index, E element)添加方式插入1000w个数,大概总耗时" + (end-begin) +"ms");
// 结果:add(int index, E element)添加方式插入1000w个数,大概总耗时3425ms
}
// addAll(Collection<? extends E> c)
public static void addAll() {
Vector<Integer> oldList = new Vector<Integer>(3);
oldList.add(111);
oldList.add(222);
oldList.add(333);
oldList.add(444);
long begin = System.currentTimeMillis();
Vector<Integer> intList = new Vector<Integer>();
intList.add(555);
intList.add(666);
intList.add(777);
for(int i=0; i<25000000; i++) {
intList.addAll(oldList);
}
long end = System.currentTimeMillis();
System.out.println("结果:addAll(Collection<? extends E> c)添加方式插入1000w个数,大概总耗时" + (end-begin) +"ms");
// 结果:addAll(Collection<? extends E> c)添加方式插入1000w个数,大概总耗时6040ms
}
// addAll(int index, Collection<? extends E> c)
public static void addAllIndex() {
Vector<Integer> oldList = new Vector<Integer>(3);
oldList.add(111);
oldList.add(222);
oldList.add(333);
oldList.add(444);
long begin = System.currentTimeMillis();
Vector<Integer> intList = new Vector<Integer>();
intList.add(555);
intList.add(666);
intList.add(777);
for(int i=0; i<250000; i++) { // 循环的次数越大,性能几号成倍增加
intList.addAll(1, oldList);
}
long end = System.currentTimeMillis();
System.out.println("结果:addAll(int index, Collection<? extends E> c)添加方式插入100w个数,大概总耗时" + (end-begin) +"ms");
// 结果:addAll(int index, Collection<? extends E> c)添加方式插入100w个数,大概总耗时36735ms
}
四)查找
1、get(int index),根据指定下标查找元素
public synchronized E get(int index) {
if (index >= elementCount) // 判断index的有效性
throw new ArrayIndexOutOfBoundsException(index);
return elementData(index);
}
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index]; // 直接返回数组下标的元素,性能较高
}
2、firstElement(),返回数组中下标为0的元素,相当于获取第一个元素
lastElement()、返回数组最后一个元素
public synchronized E firstElement() {
if (elementCount == 0) {
throw new NoSuchElementException();
}
return elementData(0);
}
public synchronized E lastElement() {
if (elementCount == 0) {
throw new NoSuchElementException();
}
return elementData(elementCount - 1);
}
3、contains(Object o),判断是否包含该元素,直接调用的indexOf(Object o, int index)方法。
containsAll(Collection<?> c),判断是否包含该集合,根据迭代集合c一个一个元素判断是否被包含。
indexOf(Object o),从头到尾查找元素是否存在集合中,返回第一个查找的元素。
indexOf(Object o, int index),返回此向量中指定元素第一次出现的索引,从 index向前index ,如未找到该元素,则返回-1。
lastIndexOf(Object o),从尾到头查找元素是否存在集合中,返回第一个查找到的元素。
lastIndexOf(Object o, int index),返回此向量中指定元素的最后一次出现的索引,从 index ,如果未找到元素,则返回-1。
五)修改
1、 set(int index, E element),修改指定index下标的元素,替换成新的element,返回被替换的元素值。
public synchronized E set(int index, E element) { // 线程安全
if (index >= elementCount) // index的有效性
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index); // 获取原先的元素,作为返回值
elementData[index] = element; // 把index下标位置替换成新的element
return oldValue;
}
2、setElementAt(E obj, int index),修改指定index下标的元素,替换成新的element,无返回值。
public synchronized void setElementAt(E obj, int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
elementData[index] = obj;
}
六)删除
1、remove(int index),删除指定index下标的元素
public synchronized E remove(int index) { // 线程安全
modCount++;
if (index >= elementCount) // 判断index是否有效
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、remove(Object o),删除指定的元素
removeElement(Object obj),删除指定的元素
removeElementAt(int index),根据指定的index下标删除元素
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) { // 判断index是否有效
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
else if (index < 0) { // 判断index是否有效
throw new ArrayIndexOutOfBoundsException(index);
}
int j = elementCount - index - 1; // 计算需要移动的下标位置
if (j > 0) { // 符合条件,把后面元素往前移动,相当于返回一个新数组
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--; // 元素个数减1
elementData[elementCount] = null; /* to let gc do its work */
}
3、clear(),删除所有元素,调用的就是removeAllElements()方法
removeAllElements(),删除所有元素
public void clear() {
removeAllElements();
}
public synchronized void removeAllElements() {
modCount++;
// Let gc do its work
for (int i = 0; i < elementCount; i++)
elementData[i] = null; // 把数组中的元素全部置空,相当于删除,数组容量不变
elementCount = 0; // 把数组存储的元素个数置为0
}
4、各种删除方式
备注:Vertor正序删除也会存在和ArrayList一样的问题。
// 正序删除
public static void removeFirst(Vector<String> list) {
for(int i=0; i<list.size(); i++) {
list.remove(i);
//list.removeElementAt(i);
}
}
// 倒序删除
public static void removeLast(Vector<String> list) {
for(int i=list.size()-1; i>=0; i--) {
list.remove(i);
//list.removeElementAt(i);
}
}
// 迭代器删除(推荐使用)
public static void removeIterator(Vector<String> list) {
Iterator<String> it = list.iterator();
while(it.hasNext()) {
it.remove();
}
}
// 迭代器集合删除,ListIterator<E>继承了Iterator<E>,原理一样
public static void removeListIterator(Vector<String> list) {
ListIterator<String> it = list.listIterator();
while(it.hasNext()) {
it.remove();
}
}
七)迭代
1、iterator()、迭代器方式
hasNext(),判断当前指针和size是否相等,如不相等,表示还有下一个元素。
next(),获取下一个元素,和hasNext()结合使用,不然容易数组越界。
remove(),删除当前的元素。
2、listIterator()、迭代器集合方式,(从0开始往后扫描删除)
ListIterator<E>继承Iterator<E>接口,所以实现了hasNext()、next()、remove()等方法。
hasNext(),判断当前指针和size是否相等,如不相等,表示还有下一个元素。
next(),获取下一个元素,和hasNext()结合使用,不然容易数组越界。
remove(),删除元素。
ListIterator<E>自定义的方法如下:
previous(),获取上一个元素。
set(E e),修改当前元素的值。
add(E e),新增元素。
3、elements()、返回此向量的组件的枚举
public Enumeration<E> elements() {
return new Enumeration<E>() { // 内部类
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");
}
};
}
各种迭代方式
// 正序迭代
public static void forFirst(Vector<String> list) {
for(int i=0; i<list.size(); i++) {
System.out.println(list.get(i));
}
}
// 倒序迭代
public static void forLast(Vector<String> list) {
for(int i=list.size()-1; i>=0; i--) {
System.out.println(list.get(i));
}
}
// 迭代器迭代(推荐使用)
public static void forIterator(Vector<String> list) {
Iterator<String> it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
// 迭代器集合迭代,ListIterator<E>继承了Iterator<E>,原理一样
public static void forListIterator(Vector<String> list) {
ListIterator<String> it = list.listIterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
// 枚举方式迭代
public static void forEnumeration(Vector<String> list) {
Enumeration<String> it = list.elements();
while(it.hasMoreElements()) {
System.out.println(it.nextElement());
}
}
八)结论
1、Vector支持传入任意指定的数据类型。
2、Vector底层是基于数组实现,所以是一个有序的集合,也可以说是一个矢量数组。
3、Vector属于线程安全。
4、Vector适合iterator()迭代、element()迭代、get(int index)查找和set(E e)修改。不适合添加和删除,会在执行时会不断创建新数组,相当于不断开辟空间,性能耗费较高。
本章完结,待续!
本文说明:该文章属于原创,如需转载,请标明文章转载来源!
上一篇: C语言 第二章