欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java Vector源码详解

程序员文章站 2022-07-14 20:01:55
...

Vector<E>源码详解(基于jdk1.8.0_162)

说明:Vector<E>底层使用了数组的方式实现,是一个线程安全的集合。

           该章只列举了常用的增删查改方法,其它可以参考JDK文档。

Stack<E>:栈的特性是“先进后出”,继承了Vector<E>类,实现的功能。

                    相当于栈的底层也是数组实现,也是一个线程安全的对象。

一)类图:

Java Vector源码详解

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)修改。不适合添加和删除,会在执行时会不断创建新数组,相当于不断开辟空间,性能耗费较高。

本章完结,待续!
 
本文说明:该文章属于原创,如需转载,请标明文章转载来源!