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

Java集合类源码解析:Vector

程序员文章站 2022-11-27 17:45:41
[学习笔记]转载 Java集合类源码解析:Vector 引言 之前的文章我们学习了一个集合类 ArrayList,今天讲它的一个兄弟 Vector。为什么说是它兄弟呢?因为从容器的构造来说,Vector 简直就是 ArrayList 的翻版,也是基于数组的数据结构,不同的是,Vector的每个方法都 ......

引言

之前的文章我们学习了一个集合类 arraylist,今天讲它的一个兄弟 vector
为什么说是它兄弟呢?因为从容器的构造来说,vector 简直就是 arraylist 的翻版,也是基于数组的数据结构,不同的是,vector的每个方法都加了 synchronized 修饰符,是线程安全的。

类声明

用idea打开 vector 的源码,不难发现,它的类声明跟 arraylist 一模一样,都是继承了abstractlist,并且都实现了randomaccess接口,遍历元素用for循环的效率要优于迭代器。

 * @author  lee boynton
 * @author  jonathan payne
 * @see collection
 * @see linkedlist
 * @since   jdk1.0
 */
public class vector<e>
    extends abstractlist<e>
    implements list<e>, randomaccess, cloneable, java.io.serializable

值得说明的是,从注释上来看,vector 是 jdk1.0版本就引进的,属于最古老的集合类的那一批,而arraylist是 1.2才引进的,所以说,vector才是哥哥,arraylist是小弟,哈哈~~~~

基本变量和构造函数

基本变量

vector 的基本变量有四个,分别是:

  • 底层数组
protected object[] elementdata;
  • 数组元素个数
protected int elementcount;
  • 增长的容量大小,如果这个值小于或等于0,扩容时会扩大 2 倍,
capacityincrement
  • 最大容量
private static final int max_array_size = integer.max_value - 8;

构造函数

//创建初识容量为10的数组,增长量0
public vector() {
    this(10);
}
//创建初识容量可变的数组,增长量为0
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);
 }

看的出来,vector的构造器和成员变量和arraylist大同小异。

成员方法

扩容

vector 与 arraylist 虽然很类似,但在扩容大小这方面还是有区别的,arraylist 默认扩容后的大小为原容量 的1.5倍,而vector则是先判断增长量大小,如果是非正数,那就扩大为原来的2倍,看一下它的扩容方法:

//参数是最小需要的容量
private void grow(int mincapacity) {
    // overflow-conscious code
    int oldcapacity = elementdata.length;
    //如果增长量不大于0,扩容为2倍大小
    //一般默认创建的容器都是不传增长量的,所以默认增长量是0,也就是默认直接扩容两倍
    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);
}
private static int hugecapacity(int mincapacity) {
        if (mincapacity < 0) // overflow
            throw new outofmemoryerror();
        return (mincapacity > max_array_size) ?
            integer.max_value :
            max_array_size;
    }

添加

vector的添加方法都是加上 synchronized关键字的,并且添加前检测容量,判断是否扩容:

//加入元素到数组结尾,同步的
public synchronized boolean add(e e) {
    modcount++;
    //检测容量
    ensurecapacityhelper(elementcount + 1);
    elementdata[elementcount++] = e;
    return true;
} 
//检测容量大小,超过数组长度就做扩容
private void ensurecapacityhelper(int mincapacity) {
    // overflow-conscious code
    if (mincapacity - elementdata.length > 0)
        grow(mincapacity);
}
public void add(int index, e element) {
    insertelementat(element, index);
}
//插入对应索引的元素
public synchronized void insertelementat(e obj, int index) {
        modcount++;
        if (index > elementcount) {
            throw new arrayindexoutofboundsexception(index
                                                     + " > " + elementcount);
        }
        ensurecapacityhelper(elementcount + 1);
        //插入元素前,把其索引后面的元素统一后移一位
        system.arraycopy(elementdata, index, elementdata, index + 1, elementcount - index);
        elementdata[index] = obj;
        elementcount++;
    }
public synchronized void addelement(e obj) {
    modcount++;
    //保证容量足够
    ensurecapacityhelper(elementcount + 1);
    //直接设置最后一个元素的数据
    elementdata[elementcount++] = obj;
}
//添加整个集合
public synchronized boolean addall(collection<? extends e> c) {
        modcount++;
        //把集合转为数组对象
        object[] a = c.toarray();
        int numnew = a.length;
        ensurecapacityhelper(elementcount + numnew);
        //直接复制集合元素到数组后面
        system.arraycopy(a, 0, elementdata, elementcount, numnew);
        elementcount += numnew;
        return numnew != 0;
    }
 //在对应的索引处插入一个集合
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;
    }

vector的添加方法代码不是很复杂,跟arraylist 一样,本质上都是对数组做插入数据的操作,不同的是,方法都加了synchronized 修饰,所以,它的添加方法都是线程安全的。

其他操作元素的方法也是这样的套路,这里不打算一一列举了,因为都跟arraylist 差不多,另外,vector 比 arraylist 多了一个迭代方法

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

返回的是一个enumeration 接口对象,大概也是个容器接口,没用过,不说太多。

vector 对比 arraylist

最后,总结一下 vector 和 arraylist 的对比吧。

相同点:

  • 底层都是基于数组的结构,默认容量都是10;

  • 都实现了randomaccess 接口,支持随机访问;

  • 都有扩容机制;

区别:

  • vector 的方法有做同步操作,是属于线程安全的,而arraylist 是非线程安全的;

  • vector默认情况下扩容后的大小为原来的2倍,而arraylist 是1.5倍;

  • vector 比 arraylist 多了一种迭代器 enumeration;

虽然vector相较arraylist做了同步的处理,但这样也影响了效率,因为每次调用方法都要获取锁,所以,一般情况下,对集合的线程安全没有需求的话,推荐使用 arraylist。

版权保护:本文为转载文章,原文地址: