Vector<E>源码详解

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

 

识别二维码关注个人微信公众号

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
vector< vector<int> > 是一个容器,其中嵌套了另一个容器。外层容器的元素类型是 vector<int>,内层容器的元素类型是 int。你可以通过以下几个步骤来使用 vector< vector<int> >: 1. 定义和长度: - 正确的定义方式:vector< vector<int> > A;(在尖括号前加上空格) - 获取 vector< vector<int> > A 中的外层容器元素个数:int len = A.size(); - 获取 vector< vector<int> > A 中第 i 个外层容器的长度:int len = A[i].size(); 2. 访问某个元素: - 在使用 vector 容器之前,需要加上 <vector> 头文件:#include <vector> - vector 属于 std 命名空间的内容,因此需要通过命名限定:using std::vector;(也可以直接使用全局的命名空间方式:using namespace std;) - 使用 vector 的成员函数来访问元素... 例如,如果想定义 A = [[0,1,2],[3,4,5]],可以按如下步骤: ```cpp vector< vector<int> > A; // 大容器 // A.push_back 里必须是 vector vector<int> B; // 小容器 B.push_back(0); B.push_back(1); B.push_back(2); A.push_back(B); // 小容器放入大容器 B.clear(); // 清空小容器元素 B.push_back(3); B.push_back(4); B.push_back(5); A.push_back(B); ``` 范例中还提供了一个案例,可以参考如下代码实现键盘输入 n 维矩阵,转化为二维向量: ```cpp #include <iostream> #include <vector> using namespace std; int main() { vector< vector<int> > v; vector<int> temp; int n, i, j, num; cout << "input the dimension:"; cin >> n; cout << "请输入" << n << "*" << n << "的矩阵" << endl; // 输入元素 for (i = 0; i < n; i++) { temp.clear(); // 清空 temp 内元素 for (j = 0; j < n; j++) { cin >> num; temp.push_back(num); } v.push_back(temp); } cout << "<----- 遍历输出所有元素 ----->" << endl; for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { cout << v[i][j] << " "; } cout << endl; } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值