ArrayList 和 Vector 的区别

1. ArrayList 是线程不安全的,Vector 是线程安全的

  • Vector 类的所有方法都是同步的。可以有两个线程安全的访问一个 Vector 对象,但是一个线程访问 Vector 的话会在同步操作上耗费大量的时间。

  • ArrayList 是线程不安全的,所以当我们不需要保证线程安全性的时候推荐使用 ArrayList,如果想要在多线程中使用 ArrayList 可以通过 Collections.synchronizedList(new ArrayList())new CopyOnWriteArrayList 的方式创建一个线程安全的 ArrayList 集合

2. ArrayList 使用默认构造器创建对象时是在调用 add() 方法时对 ArrayList 的默认容量进行初始化的,Vector 在调用构造器时就对容量进行了初始化

首先对比 ArrayList 和 Vector 的无参构造函数

// ArrayList 的无参构造函数
public ArrayList() {
    // 默认为一个空对象数组 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

// Vector 无参构造函数
public Vector() {
    this(10);
}
// 调用的 Vector 有参构造函数
// initialCapacity 为 10,capacityIncrement 没传入默认为 0 
public Vector(int initialCapacity, int capacityIncrement) {
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    // 初始化对象数组大小,对象数组大小为
    this.elementData = new Object[initialCapacity];
    this.capacityIncrement = capacityIncrement;
}

再看看 ArrayList 和 Vector 添加操作 add() 的源码

// ArrayList 的添加方法
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}
// ArrayList 在执行 add() 方法时才将对象数组进行赋值
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

// Vector 的添加方法
public synchronized boolean add(E e) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = e;
    return true;
}

3. ArrayList 存储数据的 Object 数组使用了 transient 关键字,Vector 的 Object 数组没有

transient 解释:

transient:Java 语言的关键字,变量修饰符,如果用 transient 声明一个实例变量,当对象存储时,它的值不需要维持。这里的对象存储是指,Java 的 serialization 提供的一种持久化对象实例的机制。当一个对象被序列化的时候,transient 型变量的值不包括在序列化的表示中,然而非 transient 型的变量是被包括进去的。使用情况是:当持久化对象时,可能有一个特殊的对象数据成员,我们不想用 serialization 机制来保存它。为了在一个特定对象的一个域上关闭 serialization,可以在这个域前加上关键字 transient

简单的说,就是被 transient 修饰的成员变量,在序列化的时候其值会被忽略,在被反序列化后, transient 变量的值被设为初始值, 如 int 型的是 0,对象型的是 null

4. ArrayList 和 Vector 的扩容机制不同

ArrayList 扩容源代码

private void grow(int minCapacity) {
    // 获取当前数组的长度
    int oldCapacity = elementData.length;
    // 在原数组的基础上 扩容 1.5 倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 扩容后的数组不能满足最小需求容量 数组扩容为最小需求容量
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    // 数组扩容后大于 最大数组长度 将数组最大长度设置为 Integer 的最大值,2^31-1
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // 将数组进行复制扩容
    elementData = Arrays.copyOf(elementData, newCapacity);
}

Vector 扩容源代码

private void grow(int minCapacity) {
    // 获取当前容器的长度
    int oldCapacity = elementData.length;
    // 若容器增量大于 0 则 扩容 (容器增量 + 原容器长度) 当我们不通过构造器指定 capacityIncrement 时默认容器增量为 0。容器增量不大于 0 时按 2 倍容器大小扩容
    int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                     capacityIncrement : oldCapacity);
    // 容器扩容后仍不满足需求,扩容为最小需求容量
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    // 容器扩容后大于 最大数组长度时 与 ArrayList 操作相同
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // 将数组进行复制扩容
    elementData = Arrays.copyOf(elementData, newCapacity);
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值