集合-Vector 的常用方法源码及使用场景

207 阅读4分钟

Vector

继承关系

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

从继承关系可以看出

Vector继承于AbstractList,实现了List、RandomAccess、Cloneable、 Serializable等接口。

1.Vector 继承了AbstractList,实现了List接口。

2.Vector实现了RandmoAccess接口,即提供了随机访问功能。

3.Vector 实现了Cloneable接口,即实现克隆功能。

4.Vector 实现Serializable接口,支持序列化。

构造方法和初始化

底层是动态数组实现的

protected Object[] elementData;//数组
 protected int elementCount;//放入数组的元素个数
protected int capacityIncrement;//增长系数

四个构造方法

1.传入初始大小和增长系数的构造方法

public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }

2.指定初始容量和的空向量,其增长系数为0


/**
     * Constructs an empty vector with the specified initial capacity and
     * with its capacity increment equal to zero.
     * 指定初始容量和的空向量,其容量增量为零
     */
    public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }

3.构造一个空向量,使其内部数据数组的大小为10,其标准容量增量为0

/**
     * Constructs an empty vector so that its internal data array
     * has size {@code 10} and its standard capacity increment is
     * zero.
     *构造一个空向量,使其内部数据数组的大小为{@code 10},其标准容量增量为0
     */
    public Vector() {
        this(10);
    }

4.传入一个集合构造器,并返回一个顺序的Vector

    /**
     * Constructs a vector containing the elements of the specified
     * collection, in the order they are returned by the collections iterator.
     * 构造包含指定元素的向量集合,按照集合返回的顺序迭代器
     */
    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)//判断c.toArray是否是Object[]类型
            elementData = Arrays.copyOf(elementData, elementCount, Object[].class);//复制数组构成Vector
    }

初始化

public Vector() {
        this(10);
    }

可以看出默认长度是10个。

常见api

添加

同ArrayList类似也是经历两个步骤:

1.增加数组长度,

2.将元素添加到数组中

只是增加了锁synchronized,保证线程安全。

public synchronized void addElement(E obj) {//加锁保证线程安全
        modCount++;//记录修改次数
        ensureCapacityHelper(elementCount + 1);//增加数组长度(涉及扩容)
        elementData[elementCount++] = obj;//添加元素
    }

删除

删除分为两种:

1.根据元素删除

根据元素删除的原理:先找到对应元素的下标,再根据下标删除

2.根据下标删除

根据元素的删除

//根据元素删除
public synchronized boolean removeElement(Object obj) {//加锁线程安全
        modCount++;
        int i = indexOf(obj);//找到对应元素的下标
        if (i >= 0) {
            removeElementAt(i);//根据下标删除
            return true;
        }
        return false;
    }

指定下标的删除

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) {
                //arraycopy(Object src, int srcPos, Object dest, int destPos, int length) 
		 //从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。
		 //第一个elementData:原数组
		 //第二个elementData:目标数组
		 //源数组中位置在 srcPos 到 srcPos+length-1 之间的组件被
		 //分别复制到目标数组中的 destPos 到 destPos+length-1 位置。 
		 //public static void arraycopy(Object src,int srcPos,Object dest,int destPos, int length)
            System.arraycopy(elementData, index + 1, elementData, index, j);
        }
        elementCount--;
        //此时最后的一个元素设为nul,这是数组的长度就减1了
        elementData[elementCount] = null; /* to let gc do its work */
    }

移除所有元素

循环置为null

public synchronized void removeAllElements() {
        modCount++;
        // Let gc do its work
        for (int i = 0; i < elementCount; i++)
            elementData[i] = null;

        elementCount = 0;
    }

romove方法

底层还是调用的removeElement方法

public boolean remove(Object o) {
        return removeElement(o);
    }

查询

返回对应下标的数据

public synchronized E get(int index) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        return elementData(index);
    }
    
    
    @SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

指定下标下设置值

public synchronized E set(int index, E element) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

克隆

就是创建一个新数组,将老元素复制到新的数组中,返回该Vector

public synchronized Object clone() {
        try {
            @SuppressWarnings("unchecked")
                Vector<E> v = (Vector<E>) super.clone();
            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(e);
        }
    }

扩容

扩充容量

    //扩充容量
    public synchronized void ensureCapacity(int minCapacity) {
        if (minCapacity > 0) {
            modCount++;
            ensureCapacityHelper(minCapacity);
        }
    }

扩充容量帮助函数

private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

真正的扩容方法

    //最大容量
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    //扩充容量执行方法
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        // 根据capacityIncrement进行判断,capacityIncrement> 0
        //增加capacityIncrement个容量,否则容量扩充当前容量的一倍
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        //扩容操作,生成已给新的数组,容量为newCapacity,并将elementData中的元素全部拷贝到新数组中,
        //并将新生成的数组在赋值给elementData
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8 的原因

数组作为一个对象,需要一定的内存存储对象头信息,对象头信息最大占用内存不可超过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;
    }

小结

1.Vector 可以存放null;

2.Vector线程安全;

3.Vector内部实际上是一个Object的数组;

4.Vector每次扩容是2倍;

5.Vector本质是一个数组所以查询很快,新增和删除要慢些;

6.和ArrayList类似Vector底层数组存/取元素效率非常的高(get/set),查找,时间复杂度是O(1),插入和删除元素效率时间复杂度为O(n)。

Vector 和ArrayList的区别

1.Vector线程安全,ArrayList线程不安全;

2.它们都是动态扩容的,但是Vector扩容为2倍,ArrayList扩容1.5倍;

3.ArrayList由于不需要同步,性能优于Vector。

总结

Vector 和 ArrayList 还有 LinkedList都是同一级的,它们中插入最快的是LinkedList,

因为插入数据时只需要记录当前项的前后项即可,而其他两个平均情况下需要遍历向后移动。

写在后面的话

你是守宫砂,也是明月光,世事繁复,愿你心境四季如春!