Java集合三之Vector

一:Vector简介

  1. Vector基本信息

    Vector 是矢量队列。继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口。
    Vector 继承了AbstractList,实现了List;所以,它是一个队列,支持相关的增删改、遍历等功能。
    Vector 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在Vector中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。
    Vector 实现了Cloneable接口,即实现clone()函数。它能被克隆。

    Vector非常类似ArrayList,但是Vector是同步的,并且是一个动态数组。由Vector创建的Iterator,虽然和ArrayList创建的 Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。

  2. Vector子类Stack

    Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得 Vector得以被当作堆栈使用。基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

二:Vector源码解析

创建了一个Vector向量类的对象后,可以往其中随意插入不同类的对象,即不需顾及类型也不需预先选定向量的容量,并可以方便地进行查找。对于预先不知或者不愿预先定义数组大小,并且需要频繁地进行查找,插入,删除工作的情况。可以考虑使用向量类。下面我们来分析LinkedList的源代码:

  1. 属性
    Vector定义了三个protected属性:

        //存储向量组件的数组缓冲区。
        protected Object[] elementData;
    
        //有效组件的数量
        protected int elementCount;
    
        //当矢量容量大于容量时,容量自动增加。如果容量增量小于等于零,那么向量容量每次增一倍。
        protected int capacityIncrement;

    和ArrayList、LinkedList中私有属性不一样的是,Vector定义的是protected属性;主要可用于其子类Stack对它方法和属性的继承以及后续功能的拓展,本身在实际应用中比较少。

  2. 构造方法
    Vector提供了四种构造方法:

        //初始容器10
        public Vector() {
            this(10);
        }
        //capacity是Vector的默认容量大小。每次扩容增加一倍。
        public Vector(int initialCapacity) {
            this(initialCapacity, 0);
        }
        //capacity默认容量大小,capacityIncrement每次扩容时的增量值。
        public Vector(int initialCapacity, int capacityIncrement) {
            super();
            if (initialCapacity < 0)
                throw new IllegalArgumentException("Illegal Capacity: "+
                                                   initialCapacity);
            this.elementData = new Object[initialCapacity];
            this.capacityIncrement = capacityIncrement;
        }
        //创建一个包含collection的Vector
        public Vector(Collection<? extends E> c) {
            elementData = c.toArray();
            elementCount = elementData.length;
            if (elementData.getClass() != Object[].class)
                elementData = 
                    Arrays.copyOf(elementData, elementCount, Object[].class);
        }

    使用第一、四种方法系统会自动对向量进行管理,若使用后两种方法。则系统将根据参数,initialcapacity设定向量对象的容量(即向量对象可存储数据的大小),当真正存放的数据个数超过容量时。系统会扩充向量对象存储容量。

    参数capacityincrement给定了每次扩充的扩充值。当capacityincrement为0的时候,则每次扩充一倍,利用这个功能可以优化存储。

三:Vector的方法解析

  1. 数据存储

    Vector提供了add(E e)、add(int index, E element)、addAll(Collection<?extends E> c)、addAll(int index, Collection< ? extends E> c)、addElement(E obj)这些添加元素的方法。下面我们一一讲解:

    
        // 将指定元素添加到此向量的末尾
        public synchronized boolean add(E e) {
            modCount++;
            ensureCapacityHelper(elementCount + 1);
            elementData[elementCount++] = e;
                return true;
        }
        //在此向量的指定位置插入指定的元素
        public void add(int index, E element) {
                insertElementAt(element, index);
            }
        //在指定位置将指定 Collection 中的所有元素插入到此向量中
        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;
        }
        //将指定 Collection 中的所有元素添加到此向量的末尾,按照指定 collection 的迭代器所返回的顺序添加这些元素
        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;
        }
        //将指定的组件添加到此向量的末尾,将其大小增加 1
        public synchronized void addElement(E obj) {
            modCount++;
            ensureCapacityHelper(elementCount + 1);
            elementData[elementCount++] = obj;
        }

    新增方法本身原理其实就是向动态数组中添加数据,上面代码中主要方法为ensureCapacityHelper的调用,下面我们来看看其实现:

    // 确认“Vector容量”的帮助函数
    private void ensureCapacityHelper(int minCapacity) {
        int oldCapacity = elementData.length;
        // 当Vector的容量不足以容纳当前的全部元素,增加容量大小。
        // 若 容量增量系数>0(即capacityIncrement>0),则将容量增大当capacityIncrement
        // 否则,将容量增大一倍。
        if (minCapacity > oldCapacity) {
            Object[] oldData = elementData;
            int newCapacity = (capacityIncrement > 0) ?
                (oldCapacity + capacityIncrement) : (oldCapacity * 2);
            if (newCapacity < minCapacity) {
                newCapacity = minCapacity;
            }
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
    }

    从上面我们可以看出,该方法主要用于确认“Vector容量”的帮助函数,即扩容作用,用以保证该容器的存放数组长度足够,动态添加容量。

  2. 数据读取

    //根据索引获取数据
    public synchronized E get(int index) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);
    
        return (E)elementData[index];
        }
        // 返回“Vector中全部元素对应的Enumeration”
        public Enumeration<E> elements() {
            // 通过匿名类实现Enumeration
            return new Enumeration<E>() {
                int count = 0;
    
                // 是否存在下一个元素
                public boolean hasMoreElements() {
                    return count < elementCount;
                }
    
                // 获取下一个元素
                public E nextElement() {
                    synchronized (Vector.this) {
                        if (count < elementCount) {
                            return (E)elementData[count++];
                        }
                    }
                    throw new NoSuchElementException("Vector Enumeration");
                }
            };
        }
    
        // 从index位置开始向后查找元素(o)。
        // 若找到,则返回元素的索引值;否则,返回-1
        public synchronized int indexOf(Object o, int index) {
            if (o == null) {
                // 若查找元素为null,则正向找出null元素,并返回它对应的序号
                for (int i = index ; i < elementCount ; i++)
                if (elementData[i]==null)
                    return i;
            } else {
                // 若查找元素不为null,则正向找出该元素,并返回它对应的序号
                for (int i = index ; i < elementCount ; i++)
                if (o.equals(elementData[i]))
                    return i;
            }
            return -1;
        }
    
        // 查找并返回元素(o)在Vector中的索引值
        public int indexOf(Object o) {
            return indexOf(o, 0);
        }
    
        // 从后向前查找元素(o)。并返回元素的索引
        public synchronized int lastIndexOf(Object o) {
            return lastIndexOf(o, elementCount-1);
        }
    
        // 从后向前查找元素(o)。开始位置是从前向后的第index个数;
        // 若找到,则返回元素的“索引值”;否则,返回-1。
        public synchronized int lastIndexOf(Object o, int index) {
            if (index >= elementCount)
                throw new IndexOutOfBoundsException(index + " >= "+ elementCount);
    
            if (o == null) {
                // 若查找元素为null,则反向找出null元素,并返回它对应的序号
                for (int i = index; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
            } else {
                // 若查找元素不为null,则反向找出该元素,并返回它对应的序号
                for (int i = index; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
            }
            return -1;
        }
    
        // 返回Vector中index位置的元素。
        // 若index月结,则抛出异常
        public synchronized E elementAt(int index) {
            if (index >= elementCount) {
                throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
            }
    
            return (E)elementData[index];
        }
    
        // 获取Vector中的第一个元素。
        // 若失败,则抛出异常!
        public synchronized E firstElement() {
            if (elementCount == 0) {
                throw new NoSuchElementException();
            }
            return (E)elementData[0];
        }
    
        // 获取Vector中的最后一个元素。
        // 若失败,则抛出异常!
        public synchronized E lastElement() {
            if (elementCount == 0) {
                throw new NoSuchElementException();
            }
            return (E)elementData[elementCount - 1];
        }
        // 获取Vector中fromIndex(包括)到toIndex(不包括)的子集
        public synchronized List<E> subList(int fromIndex, int toIndex) {
            return Collections.synchronizedList(super.subList(fromIndex, toIndex), this);
        }
  3. 数据修改

    // 设置index位置的元素值为obj
        public synchronized void setElementAt(E obj, int index) {
            if (index >= elementCount) {
                throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                     elementCount);
            }
            elementData[index] = obj;
        }
    
        // 设置index位置的值为element。并返回index位置的原始值
        public synchronized E set(int index, E element) {
            if (index >= elementCount)
                throw new ArrayIndexOutOfBoundsException(index);
    
            Object oldValue = elementData[index];
            elementData[index] = element;
            return (E)oldValue;
        }
  4. 数据删除

    // 删除index位置的元素
        public synchronized void removeElementAt(int index) {
            modCount++;
            if (index >= elementCount) {
                throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                     elementCount);
            } else if (index < 0) {
                throw new ArrayIndexOutOfBoundsException(index);
            }
    
            int j = elementCount - index - 1;
            if (j > 0) {
                System.arraycopy(elementData, index + 1, elementData, index, j);
            }
            elementCount--;
            elementData[elementCount] = null; /* to let gc do its work */
        }
    
        // 在Vector中查找并删除元素obj。
        // 成功的话,返回true;否则,返回false。
        public synchronized boolean removeElement(Object obj) {
            modCount++;
            int i = indexOf(obj);
            if (i >= 0) {
                removeElementAt(i);
                return true;
            }
            return false;
        }
    
        // 删除Vector中的全部元素
        public synchronized void removeAllElements() {
            modCount++;
            // 将Vector中的全部元素设为null
            for (int i = 0; i < elementCount; i++)
                elementData[i] = null;
    
            elementCount = 0;
        }
    
        // 删除Vector中的元素o
        public boolean remove(Object o) {
            return removeElement(o);
        }
    
        // 删除index位置的元素,并返回index位置的原始值
        public synchronized E remove(int index) {
            modCount++;
            if (index >= elementCount)
                throw new ArrayIndexOutOfBoundsException(index);
            Object 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
    
            return (E)oldValue;
        }
    
        // 清空Vector
        public void clear() {
            removeAllElements();
        }
    
        // 删除集合c的全部元素
        public synchronized boolean removeAll(Collection<?> c) {
            return super.removeAll(c);
        }
    
        // 删除“非集合c中的元素”
        public synchronized boolean retainAll(Collection<?> c)  {
            return super.retainAll(c);
        }
    
        // 删除Vector中fromIndex到toIndex的元素
        protected synchronized void removeRange(int fromIndex, int toIndex) {
            modCount++;
            int numMoved = elementCount - toIndex;
            System.arraycopy(elementData, toIndex, elementData, fromIndex,
                             numMoved);
    
            // Let gc do its work
            int newElementCount = elementCount - (toIndex-fromIndex);
            while (elementCount != newElementCount)
                elementData[--elementCount] = null;
        }
  5. 其他方法

    // 将数组Vector的全部元素都拷贝到数组anArray中
        public synchronized void copyInto(Object[] anArray) {
            System.arraycopy(elementData, 0, anArray, 0, elementCount);
        }
    
        // 将当前容量值设为 =实际元素个数
        public synchronized void trimToSize() {
            modCount++;
            int oldCapacity = elementData.length;
            if (elementCount < oldCapacity) {
                elementData = Arrays.copyOf(elementData, elementCount);
            }
        }
    
        // 确定Vector的容量。
        public synchronized void ensureCapacity(int minCapacity) {
            // 将Vector的改变统计数+1
            modCount++;
            ensureCapacityHelper(minCapacity);
        }
    
        // 设置容量值为 newSize
        public synchronized void setSize(int newSize) {
            modCount++;
            if (newSize > elementCount) {
                // 若 "newSize 大于 Vector容量",则调整Vector的大小。
                ensureCapacityHelper(newSize);
            } else {
                // 若 "newSize 小于/等于 Vector容量",则将newSize位置开始的元素都设置为null
                for (int i = newSize ; i < elementCount ; i++) {
                    elementData[i] = null;
                }
            }
            elementCount = newSize;
        }
    
        // 返回“Vector的总的容量”
        public synchronized int capacity() {
            return elementData.length;
        }
    
        // 返回“Vector的实际大小”,即Vector中元素个数
        public synchronized int size() {
            return elementCount;
        }
    
        // 判断Vector是否为空
        public synchronized boolean isEmpty() {
            return elementCount == 0;
        }
    
        // 返回Vector中是否包含对象(o)
        public boolean contains(Object o) {
            return indexOf(o, 0) >= 0;
        }
    
        // 克隆函数
        public synchronized Object clone() {
            try {
                Vector<E> v = (Vector<E>) super.clone();
                // 将当前Vector的全部元素拷贝到v中
                v.elementData = Arrays.copyOf(elementData, elementCount);
                v.modCount = 0;
                return v;
            } catch (CloneNotSupportedException e) {
                // this shouldn't happen, since we are Cloneable
                throw new InternalError();
            }
        }
    
        // 返回Object数组
        public synchronized Object[] toArray() {
            return Arrays.copyOf(elementData, elementCount);
        }
    
        // 返回Vector的模板数组。所谓模板数组,即可以将T设为任意的数据类型
        public synchronized <T> T[] toArray(T[] a) {
            // 若数组a的大小 < Vector的元素个数;
            // 则新建一个T[]数组,数组大小是“Vector的元素个数”,并将“Vector”全部拷贝到新数组中
            if (a.length < elementCount)
                return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());
    
            // 若数组a的大小 >= Vector的元素个数;
            // 则将Vector的全部元素都拷贝到数组a中。
        System.arraycopy(elementData, 0, a, 0, elementCount);
    
            if (a.length > elementCount)
                a[elementCount] = null;
    
            return a;
        }
    
        // 返回Vector是否包含集合c
        public synchronized boolean containsAll(Collection<?> c) {
            return super.containsAll(c);
        }
  6. Stack 子类方法

    Stack是一个后进先出(last in first out,LIFO)的堆栈,在Vector类的基础上扩展5个方法而来,下面是五个方法的源码:

    public Stack() {
        }
    
        //把项压入堆栈顶部
        public E push(E item) {
        addElement(item);
    
        return item;
        }
    
        //移除堆栈顶部的对象,并作为此函数的值返回该对象
        public synchronized E pop() {
        E   obj;
        int len = size();
    
        obj = peek();
        removeElementAt(len - 1);
    
        return obj;
        }
    
        //查看堆栈顶部的对象,但不从堆栈中移除它
        public synchronized E peek() {
        int len = size();
    
        if (len == 0)
            throw new EmptyStackException();
        return elementAt(len - 1);
        }
    
        //测试堆栈是否为空
        public boolean empty() {
        return size() == 0;
        }
    
        //返回对象在堆栈中的位置,以 1 为基数
        public synchronized int search(Object o) {
        int i = lastIndexOf(o);
    
        if (i >= 0) {
            return size() - i;
        }
        return -1;
        }

    从上面代码来看:
    Stack并不要求其中保存数据的唯一性,当Stack中有多个相同的item时,调用search方法,只返回与查找对象equal并且离栈顶最近的item与栈顶间距离(见源码中search方法说明)。

    通过peek()方法注释,可以发现数组(Vector)的最后一位即为Stack的栈顶;pop、peek以及search方法本身进行了同步;push方法调用了父类的addElement方法;empty方法调用了父类的size方法;Vector类为线程安全类;综上,Stack类为线程安全类。

四:总结

  1. Vector实际上是通过一个数组去保存数据的。当我们构造Vecotr时;若使用默认构造函数,则Vector的默认容量大小是10。
  2. 当Vector容量不足以容纳全部元素时,Vector的容量会增加。若容量增加系数 >0,则将容量的值增加“容量增加系数”;否则,将容量大小增加一倍。
  3. Vector的克隆函数,即是将全部元素克隆到一个数组中。
  4. 和ArrayList一样,遍历Vector,使用索引的随机访问方式最快,使用迭代器最慢。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值