Vector源码解析

Vector
  1. 线程安全的
    使用synchronized修饰方法。
add
    /**
     * Appends the specified element to the end of this Vector.
     *
     * @param e element to be appended to this Vector
     * @return {@code true} (as specified by {@link Collection#add})
     * @since 1.2
     */
    public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }

    /**
     * This implements the unsynchronized semantics of ensureCapacity.
     * Synchronized methods in this class can internally call this
     * method for ensuring capacity without incurring the cost of an
     * extra synchronization.
     *
     * @see #ensureCapacity(int)
     */
    private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

说明:
这里主要注意ensureCapacityHelper方法,当minCapacity - elementData.length > 0时,将调用grow方法扩容,要明确的是elementData.length指的是数组的长度,minCapacity是指当前的元素个数再加一。一开始的时候,我把elementData.length也当做元素的个数,这样的话minCapacity - elementData.length > 0就是必然成立的,那每一次add元素的时候,岂不都要进行扩容了。显然,这样理解是不对的。几番琢磨之后才醒悟过来,elementData.length值的是内部分配的数组的长度,elementData.size()才是元素的个数。这样的话,当添加元素前检测到数组已满时,就需要将数组扩容啦。数组扩容之后,再添加元素。

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

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

参数minCapacity实际上指的就是数组的最小容量,如果该值小于0的话,将会出现OutOfMemoryError内存溢出的错误,具体见hugeCapacity方法。
关于参数capacityIncrement的定义如下:

/**
     * The amount by which the capacity of the vector is automatically
     * incremented when its size becomes greater than its capacity.  If
     * the capacity increment is less than or equal to zero, the capacity
     * of the vector is doubled each time it needs to grow.
     *
     * @serial
     */
    protected int capacityIncrement;

注释上说,这个变量就是数组每次扩容时需要增加的量,假设当前数组长度是10,capacityIncrement等于5,那么,下次数组扩容后的大小就是15. 如果capacityIncrement小于或等于0的话,下次扩容时,数组长度将增加一倍。同样假设当前数组长度是10,capacityIncrement等于0,数组扩容后的大小是20,再扩容时,数组长度就是40了。
再回到grow函数,实际分配的数组大小受数组最大长度限制的,数组的最大长度限制是Integer.MAX_VALUE - 8

小插曲:
看源码的时候,我注意到grow方法是没有使用synchronized修饰的,在Vector类中,有两个对外方法可以触发grow,分别是
ensureCapacity(int minCapacity)setSize(int newSize)方法,然后我就想如果有多个线程分别执行这两个方法,触发grow函数的执行,会不会像HashMap一样在扩容的时候出现问题呢?不过后来仔细分析后发现,这里并不会有什么问题,因为HashMap里面含有链表,而Vector是纯数组操作,扩容的时候是根据索引将元素依次插入到扩容后的数组中,不依赖其他元素(链表依赖其前继节点)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值