Vector源码分析

Vector的成员变量分析

	//与ArrayList一样,Vector的底层也是使用数组elementData进行存储数据
    protected Object[] elementData;
	//当前elementData数组中元素的个数
    protected int elementCount;
	//当前elementData数组进行扩容的增量
    protected int capacityIncrement;
	//序列化版本号
    private static final long serialVersionUID = -2767605614048989439L;

小结:Vector集合的底层为数组,对Vector集合的操作,其实就是对底层elementCount数组的操作

Vector的构造方法分析

Vector构造方法有4个,分别是:

  • 无参构造:Vector();
  • 带参构造:Vector(int initialCapacity),指定initialCapacity容量大小,创建Vector集合;
  • 带参构造:Vector(int initialCapacity, int capacityIncrement),指定initialCapacity容量大小和扩容增量大小,创建Vector集合
  • 带参构造:Vector(Collection<? extends E> c),通过一个集合,创建Vector集合;
    集合;
    下面我们将通过代码来分析,每个构造方法均做了什么:
    public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        //初始化elementData数组的容量长度为initialCapacity
        this.elementData = new Object[initialCapacity];
        //设置elementData数组的扩容增量为capacityIncrement
        this.capacityIncrement = capacityIncrement;
    }
    public Vector(int initialCapacity) {
    	//初始化elementData数组的容量长度为initialCapacity,capacityIncrement ==0
        this(initialCapacity, 0);
    }
    public Vector() {
    	//初始化elementData数组的容量长度为initialCapacity==10,capacityIncrement ==0
        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);
    }

小结:

  • Vector使用无参构造初始化时,默认了底层elementData数组的长度容量为10,扩容增量为0;
  • Vector其他带参构造初始化时,传入参数或者集合,提前指定好了elementData数组的长度容量,以及扩容增量大小;

接下来思路一样,我们通过类似debug的形式调用add方法,添加第一元素,来分析Vector在add元素时,添加元素以及扩容中,整个过程中源码的具体实现

Vector的扩容源码分析

  • 我们先创建一个Vector集合,初始化容量为10,此时add第一个元素
	//创建一个Vector集合,通过上面Vector构造方法初始化,我们知道此时底层elementData数组,长度容量elementData.length==10,元素个数elementCount==0,扩容增量capacityIncrement==0
	List<String> strList = new Vector<String>()
  • 调用add(E e)方法给集合添加元素
	//添加第一个元素
	strList.add("我是第1个元素");
  • 分析add方法源码的具体实现
    public synchronized boolean add(E e) {//e="我是第1个元素"
        modCount++;
        /**
         *元素e在存储之前会调用ensureCapacityHelper(int minCapacity)方法
         *该方法具体做了什么事情,接下来我们就来分析该方法
         */
        ensureCapacityHelper(elementCount + 1);//elementCount==0
        //把元素e存放在数组elementData[elementCount++]下标位置
        elementData[elementCount++] = e;//elementData[0]="我是第1个元素"
        return true;//elementCount==1
    }

注意:Vector大量的方法基本上均加synchronized修饰,因此Vector是线程安全的,而ArrayList是没有synchronized进行修饰的,因此ArrayList不是线程安全,两个集合之间的区别,在以后我们会进行分析对比,在这里不做重点讨论

  • 分析ensureCapacityHelper(int minCapacity)方法的实现
    private void ensureCapacityHelper(int minCapacity) {//minCapacity==1
    	//elementData.length==10
        if (minCapacity - elementData.length > 0)//false,不扩容
        	//true,扩容
            grow(minCapacity);
    }

小结:当元素个数小于elementData.length时,Vector此时不进行扩容,否则超过,则Vector集合则进行扩容,当然从我们此时只add了第一个元素,不会走下面的扩容grow(int minCapacity),但是当我们元素个数超过elementData.length时,我们接着看看Vector的扩容机制是怎么实现的
注意:接下来的分析假设是add第11个元素,此时minCapacity - elementData.length > 0,
minCapacity==11,传入grow(11)

  • 分析grow(int minCapacity)方法的实现
    private void grow(int minCapacity) {//minCapacity==11
        //获取当前elementData的容量长度oldCapacity ==10
        int oldCapacity = elementData.length;
        //注意:此处由于我们使用无参构造创建的Vector的集合,扩容增量capacityIncrement==0
        //newCapacity=10+((0 > 0) ? 0 : 10 ) = 20,意味着扩容后,可能elementData.length == 20
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)//20 - 11 < 0
        	//true,则newCapacity取两者最大值
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
        	//newCapacity 最大值限定为2147483647
            newCapacity = hugeCapacity(minCapacity);
        /**
         *elementData数组按照newCapacity新的容量长度,进行数组的复制
         *然后生成新的elementData数组对象,替换掉原始旧的elementData数组对象
         *到此,elementData.length由原先的10容量长度,变成了20长度容量,扩容结束
         */
        elementData = Arrays.copyOf(elementData, newCapacity);//newCapacity==20
    }
    
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    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集合扩容的过程

  • Vector集合创建时,会初试化成员elementData数组的容量长度和扩容增量,既elementData.length和capacityIncrement
  • add元素时,元素个数size+1大于当前elementData.length时,Vector集合将进行扩容
  • 扩容标准根据capacityIncrement和elementData.length,以及当前elementCount元素个数来确定,具体可参考代码 ,最大值不能超过Integer的最大值2147483647
  • 扩容过程实际就是elementData数组按照newCapacity,进行数组的复制,生成1个新elementData数组,替换掉旧的elementData数组
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值