java中vector底层_Java数据结构漫谈-Vector

List除了ArrayList和LinkedList之外,还有一个最常用的就是Vector。

Vector在中文的翻译是矢量,向量,所以大家喜欢把Vector叫做矢量数组,或者向量数组。

其实就底层实现来说Vector与ArrayList的实现大同小异,都是使用数组作为底层的存储器,在上面进行了一些列的操作封装,而且都实现了List的数据接口。

最主要的区别就是Vector的大部分操作增加了线程同步的功能,这也是Vector与其他List最大不同的地方,Vector是线程安全的。

protectedObject[] elementData; //数组作为底层存储器protected intelementCount; //记录了当前有多少个元素了protected intcapacityIncrement; //每次扩展的时候需要扩展的数量public Vector(int initialCapacity, intcapacityIncrement) {super();if (initialCapacity < 0)throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);this.elementData = newObject[initialCapacity];this.capacityIncrement =capacityIncrement;

}public Vector(intinitialCapacity) {this(initialCapacity, 0);

}publicVector() {this(10);

}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);

}

这里面提供了与ArrayList相同的各种操作,下面简单说明一下:

1.复制内容到指定的数组,如果数组不够大,则抛出越界错误。

public synchronized voidcopyInto(Object[] anArray) {

System.arraycopy(elementData,0, anArray, 0, elementCount);

}

这里使用了System.arraycopy,后面还有很多地方使用了这个函数,其时间复杂度是o(n)。

2.在使用Vector的过程中,会出现需要扩容的情况,扩容之后又删除元素,就会造成很多元素空间被浪费的情况,如果担心浪费空间,就可以调用下面的函数进行无用空间trim:

public synchronized voidtrimToSize() {

modCount++;int oldCapacity =elementData.length;if (elementCount

elementData=Arrays.copyOf(elementData, elementCount);

}

}

可以看出这里就是开辟了一个正好需要的空间,把元素都拷贝到这个空间中,原来的数组空间会在vm空闲的时候进行回收。

3.上面说到了在数组容量不够的时候,会进行扩容,这里列出了一系列的包括扩容和获取与判断数组大小的函数:

public synchronized void ensureCapacity(intminCapacity) {//进行容量调整if (minCapacity > 0) {

modCount++;

ensureCapacityHelper(minCapacity);

}

}private void ensureCapacityHelper(intminCapacity) {//进行容量调整//overflow-conscious code

if (minCapacity - elementData.length > 0)//只有指定的容量大于元素个数的时候才进行容量调整

grow(minCapacity);

}private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;private void grow(intminCapacity) {//扩容操作//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);//开辟一个新空间,拷贝数据到新空间,旧空间将被VM自动回收

}private static int hugeCapacity(intminCapacity) {if (minCapacity < 0) //overflow

throw newOutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE) ?//其实不明白只有8的差距,为什么这么纠结Integer.MAX_VALUE :

MAX_ARRAY_SIZE;

}public synchronized void setSize(intnewSize) {//设置当前Vector的元素数量

modCount++;if (newSize >elementCount) {//比当前的元素个数大,就扩容,还不一定需要扩,看ensureCapacityHelper就明白

ensureCapacityHelper(newSize);

}else{for (int i = newSize ; i < elementCount ; i++) {//如果比当前的元素个数少,就把多出来的元素都抹掉

elementData[i]= null;

}

}

elementCount=newSize;//调整当前元素的个数

}public synchronized intcapacity() {returnelementData.length;

}public synchronized intsize() {returnelementCount;

}public synchronized booleanisEmpty() {return elementCount == 0;

}

上面的就是整个的扩容和设置元素数量等的一些操作函数的解释。

4.查找对象所在的index是List的一个重要的操作,其对应的主要的函数如下所示:

public booleancontains(Object o) {//判断一个对象o是否在Vector中return indexOf(o, 0) >= 0;

}public intindexOf(Object o) {//判断一个对象o在Vector中第一次出现的位置return indexOf(o, 0);

}public synchronized int indexOf(Object o, intindex) {//判断一个对象在Vector中的index之后第一次出现的位置if (o == null) {for (int i = index ; i < elementCount ; i++)if (elementData[i]==null)returni;

}else{for (int i = index ; i < elementCount ; i++)//使用遍历对比的方式进行判断if(o.equals(elementData[i]))returni;

}return -1;

}public synchronized intlastIndexOf(Object o) {//判断在Vector中自后向前查找对象o的第一次出现的位置return lastIndexOf(o, elementCount-1);

}public synchronized int lastIndexOf(Object o, intindex) {if (index >=elementCount)throw new IndexOutOfBoundsException(index + " >= "+elementCount);if (o == null) {for (int i = index; i >= 0; i--)if (elementData[i]==null)returni;

}else{for (int i = index; i >= 0; i--)//自后向前倒着遍历这个Vector查找if(o.equals(elementData[i]))returni;

}return -1;

}

可以看出,只要涉及到确定Vector中对象o的位置,就需要遍历对比查找,而遍历对比查找的时间复杂度是o(n)

5.根据index对Vector进行操作也有一系列的函数:

public synchronized E elementAt(intindex) {//根据index获取Vector中的元素if (index >=elementCount) {throw new ArrayIndexOutOfBoundsException(index + " >= " +elementCount);

}returnelementData(index);

}public synchronizedE firstElement() {//获取第一个元素if (elementCount == 0) {throw newNoSuchElementException();

}return elementData(0);

}public synchronizedE lastElement() {//获取最后一个元素if (elementCount == 0) {throw newNoSuchElementException();

}return elementData(elementCount - 1);

}public synchronized void setElementAt(E obj, intindex) {//设置位置为index的元素if (index >=elementCount) {throw new ArrayIndexOutOfBoundsException(index + " >= " +elementCount);

}

elementData[index]=obj;//直接设置,时间复杂度是o(1)

}public synchronized void removeElementAt(intindex) {//删除位置为index的元素

modCount++;if (index >=elementCount) {throw new ArrayIndexOutOfBoundsException(index + " >= " +elementCount);

}else if (index < 0) {throw newArrayIndexOutOfBoundsException(index);

}int j = elementCount - index - 1;if (j > 0) {//如果不是最后一个需要进行元素位移,这个时候的时间复杂度是o(n)

System.arraycopy(elementData, index+ 1, elementData, index, j);

}

elementCount--;

elementData[elementCount]= null; /*to let gc do its work*///把最后的值为null}public synchronized void insertElementAt(E obj, intindex) {//在位置中间插入一个元素,时间复杂度是o(n)

modCount++;if (index >elementCount) {throw newArrayIndexOutOfBoundsException(index+ " > " +elementCount);

}

ensureCapacityHelper(elementCount+ 1);//先进行扩容

System.arraycopy(elementData, index, elementData, index+ 1, elementCount -index);//让出位置,时间复杂度是o(n)

elementData[index]=obj;//直接赋值

elementCount++;//计数加一

}public synchronized voidaddElement(E obj) {

modCount++;

ensureCapacityHelper(elementCount+ 1);

elementData[elementCount++] =obj;//在队尾加入一个,时间复杂度是o(1)

}public synchronized booleanremoveElement(Object obj) {//删除Vector中出现的第一个对象obj

modCount++;int i =indexOf(obj);if (i >= 0) {

removeElementAt(i);return true;

}return false;

}public synchronized voidremoveAllElements() {//删除所有的元素,遍历,时间复杂度是o(n)

modCount++;//Let gc do its work

for (int i = 0; i < elementCount; i++)

elementData[i]= null;

elementCount= 0;

}public synchronizedObject clone() {//拷贝一个对象,时间复杂度是o(n)try{

@SuppressWarnings("unchecked")

Vector v = (Vector) super.clone();

v.elementData=Arrays.copyOf(elementData, elementCount);

v.modCount= 0;returnv;

}catch(CloneNotSupportedException e) {//this shouldn't happen, since we are Cloneable

throw newInternalError(e);

}

}public synchronizedObject[] toArray() {//转换成数组,时间复杂度是o(n)returnArrays.copyOf(elementData, elementCount);

}

@SuppressWarnings("unchecked")public synchronized T[] toArray(T[] a) {//转换成数组,时间复杂度是o(n)if (a.length

System.arraycopy(elementData,0, a, 0, elementCount);if (a.length >elementCount)

a[elementCount]= null;returna;

}

@SuppressWarnings("unchecked")

E elementData(intindex) {//获取index对应的对象,时间复杂度是o(1)return(E) elementData[index];

}public synchronized E get(intindex) {//获取index对应的对象,时间复杂度是o(1)if (index >=elementCount)throw newArrayIndexOutOfBoundsException(index);returnelementData(index);

}public synchronized E set(intindex, E element) {//设置index对应的对象,时间复杂度是o(1)if (index >=elementCount)throw newArrayIndexOutOfBoundsException(index);

E oldValue=elementData(index);

elementData[index]=element;returnoldValue;

}public synchronized booleanadd(E e) //在最后添加一个对象,时间复杂度是o(1),但有可能触发扩容操作

modCount++;

ensureCapacityHelper(elementCount+ 1);

elementData[elementCount++] =e;return true;

}public booleanremove(Object o) {//删除第一次出现的对象o,时间复杂度是o(n)returnremoveElement(o);

}public void add(intindex, E element) {//在inedx上添加一个元素,时间复杂度是o(n),因为会触发元素位移

insertElementAt(element, index);

}public synchronized E remove(intindex) {//删除index上面的元素,时间复杂度是o(n),因为会触发元素位移

modCount++;if (index >=elementCount)throw newArrayIndexOutOfBoundsException(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

returnoldValue;

}

以上是进行获取,增加和删除操作的时间复杂度。

再次强调,Vector在涉及到元素更改的函数之前都加了关键字synchronized,是线程安全的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值