Vector 类的所有方法都是同步的。可以有两个线程安全的访问一个 Vector 对象,但是一个线程访问 Vector 的话会在同步操作上耗费大量的时间。
ArrayList 是线程不安全的,所以当我们不需要保证线程安全性的时候推荐使用 ArrayList,如果想要在多线程中使用 ArrayList 可以通过 Collections.synchronizedList(new ArrayList()) 或 new CopyOnWriteArrayList 的方式创建一个线程安全的 ArrayList 集合
首先对比 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; }transient 解释:
transient:Java 语言的关键字,变量修饰符,如果用 transient 声明一个实例变量,当对象存储时,它的值不需要维持。这里的对象存储是指,Java 的 serialization 提供的一种持久化对象实例的机制。当一个对象被序列化的时候,transient 型变量的值不包括在序列化的表示中,然而非 transient 型的变量是被包括进去的。使用情况是:当持久化对象时,可能有一个特殊的对象数据成员,我们不想用 serialization 机制来保存它。为了在一个特定对象的一个域上关闭 serialization,可以在这个域前加上关键字 transient。
简单的说,就是被 transient 修饰的成员变量,在序列化的时候其值会被忽略,在被反序列化后, transient 变量的值被设为初始值, 如 int 型的是 0,对象型的是 null。
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); }