java集合之Vector超级详细源码解析

1.Vector介绍

Vector 和前面说的 ArrayList 很是类似,这里说的也是1.8版本,它是一个队列,但是本质上底层也是数组实现的。同样继承 AbstractList ,实现了 List , RandomAcess , Cloneable , java.io.Serializable 接口。具有以下特点:

  • 提供随机访问的功能:实现 RandomAcess 接口,这个接口主要是为 List 提供快速访问的功能,也就是通过元素的索引,可以快速访问到。
  • 可克隆:实现了 Cloneable 接口
  • 是一个支持新增,删除,修改,查询,遍历等功能。
  • 可序列化和反序列化
  • 容量不够,可以触发自动扩容
  • 最大的特点是:线程安全的 ,相当于线程安全的 ArrayList 。

定义源码如下:

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

    }

2. 成员变量

底层是数组,增加元素,数组空间不够的时候,需要扩容。

  • elementData:真正保存数据的数组
  • elementCount:实际元素个数
  • capacityIncrement:容量增加系数,就是扩容的时候增加的容量
  • serialVersionUID:序列化id
// 真正保存数据的数组
    protected Object[] elementData;

    // 元素个数
    protected int elementCount;

    //容量增加系数
    protected int capacityIncrement;
    // 序列化id
    private static final long serialVersionUID = -2767605614048989439L;

3. 构造函数

Vector 一共有四个构造函数:

  • 指定容量和增长系数
  • 指定容量
  • 不指定,使用默认容量值10
  • 指定集合初始化

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

public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }

3.什么都不指定,默认给的容量是10:

public Vector() {
        this(10);
    }

4.指定集合初始化:

public Vector(Collection<? extends E> c) {
        // 转换成为数组
        Object[] a = c.toArray();
        // 大小为数组的大小
        elementCount = a.length;
        // 如果是ArrayList,则直接复制
        if (c.getClass() == ArrayList.class) {
            elementData = a;
        } else {
            // 否则需要进行拷贝
            elementData = Arrays.copyOf(a, elementCount, Object[].class);
        }
    }

4. 常用方法

4.1 增加

增加元素,默认是在最后添加,如果容量不够的时候会触发扩容机制。

public synchronized void addElement(E obj) {
        // 修改次数增加
        modCount++;
        // 确保容量足够(如果需要,里面会有扩容,复制操作)
        ensureCapacityHelper(elementCount + 1);
        // 将新元素放在最后一个元素,个数增加
        elementData[elementCount++] = obj;
    }

那么它是如何确保容量的呢?

可以看到 ensureCapacityHelper() 里面判断增加后的元素个数是否大于现在数组的长度,如果不满足,就需要扩容。调用 grow() 函数扩容。

private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    // 扩容,传入的是需要最小的容量
    private void grow(int minCapacity) {
        // overflow-conscious code
        // 以前的容量
        int oldCapacity = elementData.length;
        // 现在的容量,是以前的容量加上扩展系数,如果扩展系数小于等于0,那么,就是以前的容量的两倍
        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);
    }

在指定的索引index,插入数据,实际上调用的是 insertElementAt(element, index) .

public void add(int index, E element) {
        insertElementAt(element, index);
    }
    // 调用插入元素的函数
    public synchronized void insertElementAt(E obj, int index) {
        // 修改次数增加
        modCount++;
        // 判断索引是否非法
        if (index > elementCount) {
            throw new ArrayIndexOutOfBoundsException(index
                                                     + " > " + elementCount);
        }
        // 确保容量足够
        ensureCapacityHelper(elementCount + 1);
        // 拷贝数据,将后面的元素,往后移动一位
        System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
        // 将实际的数据插入
        elementData[index] = obj;
        // 个数增加
        elementCount++;
    }

将一个集合所有元素添加进去:

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

指定index,插入一个集合,和前面不一样的地方在于复制之前,需要计算往后面移动多少位,不是用for循环去插入,而是一次性移动和写入。

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;
        // 插入元素个数是否为0
        return numNew != 0;
    }

4.2 删除

删除指定元素

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

    // 实际调用的是removeElement()
    public synchronized boolean removeElement(Object obj) {
        // 修改次数增加
        modCount++;
        // 获取第一个满足条件的元素缩影
        int i = indexOf(obj);
        // 索引如果满足条件
        if (i >= 0) {
            // 将索引为i的元素从数组中移除
            removeElementAt(i);
            return true;
        }
        return false;
    }
    // 操作数组删除元素
   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值