java Collection-Vector

一、Vector的概念

1.vector实现了一个可以自动增长的对象数组,类似于动态数组,能够动态的调整自身的大小,能够根据索引进行查询;

2.vector继承了AbstractList,实现了List,是一个队列,实现了相应的增删改查等功能;

3.vector实现了RnadomAccess接口,因此能够对数据进行随机访问;

4.vector的操作是线程安全的,Vector中的大部分方法增加了ychronized关键字修饰;

二、Vector的源码分析

1.Vector中的成员变量

   elementData是一个数组类型,初始化的大小是10,会随着元素的增多不断的增长。

   elementCount是数组中元素的个数。

   capacityIncrement是数组在扩容时增长的系数,如果不指定这个系数的大小时,默认为0,如果capacityIncrement<=0时,那么每次扩容elementData的时候就是直接翻倍。

protected Object[] elementData;
protected int elementCount;
protected int capacityIncrement;

2.Vector的初始化

Vector的初始化有四种方法:

    默认情况下初始化elementData数组的大小为10,capacityIncrement扩容系数为0,在使用时也可以自己指定这几个参数的大小,但是数组的大小必须是正数。

    当初始化指定的集合时,数组的中的元素为集合中的元素,数组的大小为集合的大小。

//不指定任何参数时,默认数组的大小为10
public Vector() {
	this(10);
}
//仅指定数组的大小
public Vector(int initialCapacity) {
	this(initialCapacity, 0);
}
//指定数组的大小和扩容系数
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();
	elementCount = elementData.length;
	// c.toArray might (incorrectly) not return Object[] (see 6260652)
	if (elementData.getClass() != Object[].class)
	    elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}

3.Vector中增加和减少数组大小

    在Vector中由于数据量是不固定大小的,当数据量超过当前的容量时,需要对数组的容量进行扩容。每次扩容的大小是由三个参数来决定的:扩容的目标大小minCapacity、扩容系数capacityIncrement以及当前数组的容量大小,如果目标大小小于当前数组的容量,就不需要再进行扩容操作,否则先将数组的容量按照capacityIncrement进行扩容,若扩容后的大小仍小于目标大小,那么就将容量大小改为目标大小。

    注意:在后面的方法中也可以看到,每次对Vector进行结构改变的操作,例如insert、add等都会执行ensyreCapacityHelper方法对Vector的容量进行检查,而在进行扩容操作时存在数组的复制等操作,因此如果存在插入大量元素的操作时,可以提前执行一次扩容操作,减少执行ensureCapacityHelper的操作,可以提高Vector中某些方法的执行效率。

    在每次执行增加元素的操作时,方法会自动调用ensureCapacityHelper的操作,使用者可以不用去担心容量是否够用,但是如果Vector的容量远大于其中存储的元素的个数时,也会存在空间的浪费,那么就可以调用trimSize方法,对Vector的中未使用到的空间进行释放。

 //减少数组占用的空间:当数组中实际存储的元素个数小于数组的容量时,可以减少数组的容量为实际存储元素大小的容量--存在元素的复制
public synchronized void trimToSize() {
	modCount++;
	int oldCapacity = elementData.length;
	if (elementCount < oldCapacity) {
	    elementData = Arrays.copyOf(elementData, elementCount);
	}
}
//扩展数组的容量大小为指定的minCapacity大小,如果数组的容量小于指定的容量,先按照capacityIncrement系数进行扩容,如果还是小于指定的容量,则扩容到指定的容量
//如果数组中要一次性增加大量元素时,可以先调用这个方法对数组进行扩容,避免在每次add时去扩容,减少扩容的次数
public synchronized void ensureCapacity(int minCapacity) {
	modCount++;
	ensureCapacityHelper(minCapacity);
}
        
//对数组进行扩容,这个方法不是同步的,该类中的同步方法可以在内部调用这个,确保生产能力但是不花费额外的成本去进行同步--存在元素的复制
private void ensureCapacityHelper(int minCapacity) {
	int oldCapacity = elementData.length;
	if (minCapacity > oldCapacity) {
		Object[] oldData = elementData;
		int newCapacity = (capacityIncrement > 0) ?(oldCapacity + capacityIncrement) : (oldCapacity * 2);
	    	if (newCapacity < minCapacity) {
			newCapacity = minCapacity;
		}
	        elementData = Arrays.copyOf(elementData, newCapacity);
	}
}

4.Vector中的遍历方法

    Vector主要有四种遍历方法:

//通过Iterator进行遍历
Object obj = null;
Iterator<Object> iter = vector.iterator();
while(iter.hasNext()) {
	obj = iter.next();
}
//随机访问,通过索引进行遍历
Object obj1 = null;
int size = vector.size();
for(int i = 0; i< size; i++) {
	obj1 = vector.get(i);
}
		
//通过for循环遍历
Object obj2 = null;
for(Object o : vector) {
	obj2 = o;
}
		
//通过Enumeration遍历
Object obj3 = null;
Enumeration enumer = vector.elements();
while(enumer.hasMoreElements()) {
	obj3 = enumer.nextElement();
}

测试这四种方法遍历的效率:

public static void VectorTest1() {
	Vector vector = new Vector();
	long s1 = System.currentTimeMillis();
	for(int i = 0; i< 10000000; i++) {
		vector.add(i);
	}
	//System.out.println("初始化时间:"+(System.currentTimeMillis()-s1));
	s1 = System.currentTimeMillis();
	//通过Iterator进行遍历
	Object obj = null;
	Iterator<Object> iter = vector.iterator();
	while(iter.hasNext()) {
		obj = iter.next();
	}		
	System.out.println("iterator花费时间:"+(System.currentTimeMillis()-s1));
		
	s1 = System.currentTimeMillis();
	//随机访问,通过索引进行遍历
	Object obj1 = null;
	int size = vector.size();
	for(int i = 0; i< size; i++) {
		obj1 = vector.get(i);
	}		
	System.out.println("索引遍历花费时间:"+(System.currentTimeMillis()-s1));
		
	s1 = System.currentTimeMillis();
	Object obj2 = null;
	for(Object o : vector) {
		obj2 = o;
	}
	System.out.println("for循环花费时间:"+(System.currentTimeMillis()-s1));
		
	s1 = System.currentTimeMillis();
	//通过Enumeration遍历
	Object obj3 = null;
	Enumeration enumer = vector.elements();
	while(enumer.hasMoreElements()) {
		obj3 = enumer.nextElement();
	}		
	System.out.println("Enumeration花费时间:"+(System.currentTimeMillis()-s1));
}

  5.Vector中其他的主要方法

方法说明备注
void setSize(int newSize)修改vector中包含的元素的个数

如果newSize小于当前vector的size,对vector进行截取,

只保留newSize个;

如果大于则先扩容,然后重置vector大小

int capacity()返回当前vector的容量大小 
int size()返回当前vector包含的元素个数 
boolean isEmpty()判断vector是否为空 
boolean contains(Object o)判断Vector中是否包含元素o对Vector进行遍历获取
int indexOf(Object o)返回Vector中元素o的索引位置对Vector进行遍历,返回第一个包含元素o的位置
int indexOf(Object o, int index)从index位置开始查询,返回元素o的位置直接从数组的尾部向前遍历,第一次出现的位置
int lastIndexOf(Object o, int index)从index位置向前查询,最后一次 

E elementAt(int index)

E get(int index)

返回index位置的元素值需要对index进行边界校验,直接根据索引取元素值班,效率高
E firstElement()返回第一个元素值直接去index=0位置的值
E lastElement()返回最后一个元素值 

void setElementAt(E obj, int index)

修改index位置的元素值为obj 
void removeElementAt(int index)删除index位置的元素值

需要进行边界校验,存在数组的复制,

将index位置之后的所有元素向前移动一位,数据量大时效率较高

void insetElementAt(E obj, int index)

void add(int index, E element)

插入一个元素在index位置

需要进行index的边界校验

vector需要进行扩容操作

存在数组的移动复制

void addElement(E obj)

boolean add(E e)

在数组的最后插入一个元素

vector进行扩容操作,直接插入到最后的位置

与insertElementAt方法相比效率较高

boolean removeElement(Object obj)

boolean remove(Object o)

删除一个元素

首先调用indexOf方法获取元素所在的位置,然后进行删除

,也存在数组的移动和复制操作

Object[] toArray()将vector转化为数组包含vector中的所有元素
<T> T[] toArray(T[] a)将vector转化为指定的数组

包含vector中的所有元素,如果a的长度大于vector.size

,那么将后面的值用null补齐

E set(int index, E element)修改index位置的元素值,返回替换前的值 
E remove(int index)删除index位置的值,返回删除前的值与removeElementAt(int index)相同,区别在于此方法有返回值
boolean containsAll(Collection<?> c)判断vector中是否包含指定集合中的所有元素

对c进行遍历,取c中的值去挨个判断是否在vector中,

只要有一个不再,则返回false

boolean addAll(Collection<?> c)将C中的所有元素加到vector中 
boolean retainAll(Collection<?> c)判断vector中是否有元素不再C中只要vector中有一个元素不再C中,则返回true
boolean addAll(int index, Collection<?> c)在指定位置插入c中的所有元素存在数组元素的移动和复制,效率较低
boolean equals(Object o)判断两个集合是否相等

一是比较两个集合的类型是否相同

二是比较两个集合中包含的元素个数是否相同

三是比较两个集合中所有的元素值是否相等

List<E> subList(int fromIndex, int toIndex)

截取vector,返回的类型为List,

返回值时索引值为fromIndex-toIndex之间的值

需要进行边界校验
void removeRange(int fromIndex, int toIndex)删除vector中索引值为fromIndex到toIndex之间的元素 
   

三、Vector的使用

    Vector为存储的对象分配的是一块连续的存储空间,他的本质上是一个动态数组,可以通过索引进行访问,因此随机访问的效率很高,但是在Vector中插入或删除一个元素时,会对数组中的元素进行复制和移动操作,当Vector中存储的数据量很大的情况下,对元素的进行复制操作时开销比较大。

    而List中的元素是以链表的形式存储的,当访问一个元素的时候都需要对链表进行遍历,但是相比较Vector,List的插入和删除元素操作比较方便。

    因此Vector比较适用于:对象的数量变化较少,简单对象,随机访问较频繁的情况中,而List比较适用于对象数量变化大,对象比较负责,频繁插入和删除操作的情况。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值