• jdk1.8-Vector


    一:先看下类的继承关系
    UML图如下:

    继承关系:
    public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    RandmoAccess快速随机访问接口

    二:看下成员属性
    /**
    * The array buffer into which the components of the vector are
    * stored. The capacity of the vector is the length of this array buffer,
    * and is at least large enough to contain all the vector's elements.
    *
    * <p>Any array elements following the last element in the Vector are null.
    *
    * @serial
    */
    protected Object[] elementData;
    分析:该数组缓冲区是存储vector元素,并且至少足够大到包含vector的所有元素

    /**
    * The number of valid components in this {@code Vector} object.
    * Components {@code elementData[0]} through
    * {@code elementData[elementCount-1]} are the actual items.
    *
    * @serial
    */
    protected int elementCount;
    分析:vector中实际元素的数量


    /**
    * 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;
    分析:vector增加的容量capacityIncrement,如果vector实际元素数量大于当前容量,vector将自动扩容,扩容的容量为当前容量加上capacityIncrement。如果没有指定增加的容量,那么vector在扩容时成倍的增长。

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -2767605614048989439L;
    分析:版本号

    三:构造函数
    /**
    * Constructs an empty vector so that its internal data array
    * has size {@code 10} and its standard capacity increment is
    * zero.
    */
    public Vector() {
    this(10);
    }
    分析:无参构造函数vector会初始化一个长度为10的空数组,它的标准容量增量为0(ps:也就是上面提到的capacityIncrement = 0)

    /**
    * Constructs an empty vector with the specified initial capacity and
    * with its capacity increment equal to zero.
    *
    * @param initialCapacity the initial capacity of the vector
    * @throws IllegalArgumentException if the specified initial capacity
    * is negative
    */
    public Vector(int initialCapacity) {
    this(initialCapacity, 0);
    }
    分析:指定vector初始化长度,构造一个指定的长度空数组,它的标准容量增量为0。

    /**
    * Constructs an empty vector with the specified initial capacity and
    * capacity increment.
    *
    * @param initialCapacity the initial capacity of the vector
    * @param capacityIncrement the amount by which the capacity is
    * increased when the vector overflows
    * @throws IllegalArgumentException if the specified initial capacity
    * is negative
    */
    public Vector(int initialCapacity, int capacityIncrement) {
    super();
    if (initialCapacity < 0)
    throw new IllegalArgumentException("Illegal Capacity: "+
    initialCapacity);
    //初始化长度为传进来长度的空数组
    this.elementData = new Object[initialCapacity];
    //容量增加值为传进来的capacityIncrement值
    this.capacityIncrement = capacityIncrement;
    }
    分析:指定初始化长度和容量增量值

    /**
    * Constructs a vector containing the elements of the specified
    * collection, in the order they are returned by the collection's
    * iterator.
    *
    * @param c the collection whose elements are to be placed into this
    * vector
    * @throws NullPointerException if the specified collection is null
    * @since 1.2
    */
    public Vector(Collection<? extends E> c) {
    //将集合转为数组,赋值给Object数组elementData
    elementData = c.toArray();
    //vector长度等于集合长度
    elementCount = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    //c.toArray方法返回的数据错误,重新拷贝
    if (elementData.getClass() != Object[].class)
    elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
    }
    分析:传入指定的集合,将集合元素赋值给vector


    四:看下主要的方法
    1.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) {
    //抽象父类AbstractList的成员变量,修改次数记录
    modCount++;
    //保证容量足够大
    ensureCapacityHelper(elementCount + 1);
    //elementCount是当前元素个数,数组下标是从0开始的,所以elementData[elementCount]是当前需要添加元素的位置
    //elementCount++
    elementData[elementCount++] = e;
    return true;
    }
    分析:这里我们可以看到vector的添加方法,直接加了个synchronized锁,添加方法是线程安全的,但是直接用synchronize也导致效率低下,所以我们现在基本不用vector但是了解它还是有必要的,因为stack栈是继承自它的。
    同时,这里的添加方法,逻辑处理很简单,就是先判断下vector需不需要扩容,然后根据下标索引往数组里添加值。

    我们继续看戏vector需不需要扩容方法
    ensureCapacityHelper(elementCount + 1);
    分析:方法参数为当前vector实际个数 + 1

    /**
    * 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
    //如果传进来的值大于当前vector容量数组长度,调用grow方法
    if (minCapacity - elementData.length > 0)
    grow(minCapacity);
    }
    分析:这里没有加锁操作,因为调用这个方法的外部方法都是加了锁保证了同步,这里就没必要再进行加锁产生额外的性能消耗。

    private void grow(int minCapacity) {
    // overflow-conscious code
    //旧的数组容量(长度大小)
    int oldCapacity = elementData.length;
    //如果指定了增加容量值capacityIncrement的值大于0,那么新的容量为原来容量加上capacityIncrement值大小
    //否则新的容量扩大为原来容量的两倍
    int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
    capacityIncrement : oldCapacity);
    //判断扩容后的容量是否小于传进来的vector最小容量,那么新的容量等于需要的最小容量
    if (newCapacity - minCapacity < 0)
    newCapacity = minCapacity;
    //如果扩容后的容量大于规定的最大值Integer.MAX_VALUE - 8
    if (newCapacity - MAX_ARRAY_SIZE > 0)
    //根据当前能容纳所有数据最小容量值minCapacity进行判断newCapacity的容量大小
    newCapacity = hugeCapacity(minCapacity);
    //将旧数组数据拷贝到新数组
    elementData = Arrays.copyOf(elementData, newCapacity);
    }
    分析:grow方法也就是真正进行vector扩容逻辑判断方法。这里我们需要掌握两点
    1.无额外的加锁操作,原理同上
    2.扩容机制:
    如果指定了增加容量值capacityIncrement的值大于0,那么新的容量为原来容量加上capacityIncrement值大小,否则新的容量扩大为原来容量的两倍。

    2.remove()方法
    /**
    * Removes the element at the specified position in this Vector.
    * Shifts any subsequent elements to the left (subtracts one from their
    * indices). Returns the element that was removed from the Vector.
    *
    * @throws ArrayIndexOutOfBoundsException if the index is out of range
    * ({@code index < 0 || index >= size()})
    * @param index the index of the element to be removed
    * @return element that was removed
    * @since 1.2
    */
    public synchronized E remove(int index) {
    //修改次数加1
    modCount++;
    //校验下标是否越界
    if (index >= elementCount)
    throw new ArrayIndexOutOfBoundsException(index);
    //根据索引取出旧的值
    E oldValue = elementData(index);
    //需要移动的元素个数
    int numMoved = elementCount - index - 1;
    if (numMoved > 0)
    //elementData数组从index+1位置的元素开始读取元素,拷贝到elementData数组下标从index开始,长度为mumMoved
    //相当于从index + 1位置往后的元素都往左移动一个下标
    System.arraycopy(elementData, index+1, elementData, index,
    numMoved);
    //数组末尾置为null,索引减1
    elementData[--elementCount] = null; // Let gc do its work

    return oldValue;
    }
    分析:删除操作也添加了synchronized锁,因此也是线程安全的,其它操作比较简单,直接看注释。

    总结:vector因为为了线程安全采用直接加synchronized锁,导致了性能是比较低下的,在业务上用到vector的场景不多,所以我们就简单分析,了解一下就好。
    到此,vector分析就告一段落了。


    有疑问,扫我二维码添加微信,欢迎骚扰!
    坚持做一件事,一起学习。

  • 相关阅读:
    文档01_基础
    文档07_JavaScript_ajax
    文档02_JavaScript
    文档06_JavaScript_面相对象
    文档05_JavaScript_节点
    文档06_Asp.net2.0_01
    文档04_JavaScript_事件
    文档05_多线程
    文档03_JavaScript_函数
    根据日期计算星座
  • 原文地址:https://www.cnblogs.com/lizb0907/p/10542525.html
Copyright © 2020-2023  润新知