容器(七):垂垂老矣Vector

容器(七):垂垂老矣Vector

标签: Java编程思想


Vector是List家族里的老资格了,在JDK1.0,还没有List的时候,Vector就已经开始为Collection家族效力了,在JDK1.2以后,并入到List中。随着时间的变迁,这个第一代容器早已经打上了“不推荐使用”的标签。

一道面试题

之前看过一篇面经,问题是ArrayList和Vector的区别:

ArrayList,Vector主要区别为以下几点:

  1. Vector是线程安全的,源码中有很多的synchronized可以看出,而ArrayList不是。导致Vector效率无法和ArrayList相比;
  2. ArrayList和Vector都采用线性连续存储空间,当存储空间不足的时候,ArrayList默认增加为原来的50%,Vector默认增加为原来的一倍;
  3. Vector可以设置capacityIncrement,而ArrayList不可以,从字面理解就是capacity容量,Increment增加,容量增长的参数。

Vecotor唯一的优势就是线程安全,但是现在有Collections.synchronizedListt方法拿同步的List,因此不推荐使用Vector了。

什么是Vector

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

Vector 和 ArrayList 一样,都是继承自 AbstractList。它是 Stack 的父类。英文的意思是 “矢量”。

Vector 成员变量

//底层也是个数组
protected Object[] elementData;

//数组元素个数
protected int elementCount;

//扩容时增长数量,允许用户自己设置。如果这个值是 0 或者 负数,扩容时会扩大 2 倍,而不是 1.5
protected int capacityIncrement;

//给定一个最大的容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

Vector 的构造方法

默认无参构造器

实际上是调用含参数的构造器,只是默认的数组容量为10:

//创建默认容量 10 的数组,同时增长量为 0 
public Vector() {
        this(10);
    }

指定容量构造器

实际上是调用指定容量和增长量的构造器,只是默认的增长量为0:

//创建一个用户指定容量的数组,同时增长量为 0 
public Vector(int capacity) {
    this(capacity, 0);
}

指定容量和增长量的构造器

我们通过构造函数可以看出,Vector的底层是一个Object类型的数组,指定了扩容时的增长量。

//创建指定容量大小的数组,设置增长量。如果增长量为非正数,扩容时会扩大两倍
public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }

包含集合的构造器

//创建一个包含指定集合的数组
public Vector(Collection<? extends E> c) {
    //转成数组,赋值
    elementData = c.toArray();
    elementCount = elementData.length;

    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    //可能有这个神奇的 bug,用 Arrays.copyOf 重新创建、复制
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}

Vector中的扩容方法

与ArrayList.grow(int) 很相似,只是扩大量不同:

private void grow(int minCapacity) {
    // 原先的底层数组的大小
    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;
    }

Vector的添加元素的方法

确保容量

检查数量,准备扩容

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

其他方法

因为Vector不怎么用了,而且方法很多,我就不想挨个去看源码了。要用的时候查阅API就好了

Vector遍历

Vector支持4种遍历方式。

随机访问

因为Vector实现了RandmoAccess接口,可以通过下标来进行随机访问。

for(int i = 0 ; i < vec.size() ; i++){  
        value = vec.get(i);  
    }  

迭代器

Iterator it = vec.iterator();  
    while(it.hasNext()){  
        value = it.next();  
        //do something  
    }  

for循环

for(Integer value:vec){  
        //do something  
    }  

Enumeration循环

Vector vec = new Vector<>();  
    Enumeration enu = vec.elements();  
    while (enu.hasMoreElements()) {  
        value = (Integer)enu.nextElement();  
    }  

总结

Vector 特点:

  • 底层由一个可以增长的数组组成
  • Vector 通过 capacity (容量) 和 capacityIncrement (增长数量) 来尽量少的占用空间
  • 扩容时默认扩大两倍
  • 最好在插入大量元素前增加 vector 容量,那样可以减少重新申请内存的次数
  • 通过 iterator 和 lastIterator 获得的迭代器是 fail-fast 的
  • 通过 elements 获得的老版迭代器 Enumeration 不是 fail-fast 的
    同步类,每个方法前都有同步锁 synchronized

Vector VS ArrayListde 共同点:

  • 都是基于数组
  • 都支持随机访问
  • 默认容量都是 10
  • 都有扩容机制

Vector VS ArrayListde 区别:

  • Vector 出生的比较早,JDK 1.0 就出生了,ArrayList JDK 1.2 才出来
  • Vector 比 ArrayList 多一种迭代器 Enumeration
  • Vector 是线程安全的,ArrayList 不是
  • Vector 默认扩容 2 倍,ArrayList 是 1.5

其实现在不管有没有线程安全都需求,都不推荐使用Vector。

ps:用心学习,喜欢的话请点赞 (在左侧哦)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值