一、概述
我们都知道,在Java的Collections包含了List和Set,而List里面有
ArrayList、
LinkedList、还有Vector,对于很多Java初学者来说,前面两个比较常用,ArrayList查询效率比较高(底层是数组实现),而LinkedList的增删效率比较高(底层是双向链表实现)。那么Vector是什么呢?它和ArrayList、LinkedList一样,支持有序可重复地存放单列数据。它底层实现和ArrayList类似,都是数组实现,因此在技术面试中, 面试官比较喜欢拿ArrayList和Vector进行比较。尽管Vector在Java1.2之后进行了优化更新,但是Java官方还是推荐在不需要考虑线程安全的情况下,优先使用ArrayList。
二、Vector和ArrayList的对比
那么,Vector和ArrayList既然都是数组实现,它们到底有什么区别呢?通过对比它们的源码,可以总结出以下两个区别: (1) Vector的所有方法都是有synchronized关键字的,即每一个方法都是同步的,所以在使用起来效率会非常低,但是保证了线程安全;而ArrayList的全部方法都是非同步的,所以相对Vector的效率会更高,所以它是线程不安全的。 (2) ArrayList在每次扩容时都是增加当前容量的1.5倍,而Vector在扩容时都是增加当前容量的两倍。
综上,Vector在增删改查等API上的实现都是和ArrayList类似甚至是相同的,所以如果你看了ArrayList的源码,那么Vector的源码你肯定是一下就看懂了,如果你还没看ArrayList的源码,请移步到
《Java容器类源码-ArrayList的最全的源码分析》。所以在不需要考虑线程安全时,Java官方推荐我们使用ArrayList,那么,如果线程不安全时呢?我们应该怎么选择?我们都知道,Java在Collections类中给我们提供了同步ArrayList的方法
public static <T> List<T> synchronizedList(List<T> list)。它可以帮助我们实现同步ArrayList,但是你通过看
synchronizedList的实现就会知道,它其实是创建了一个新的类叫做
SynchronizedList,它其实只是对ArrayList的增删改查等常用方法加了synchronized字段,所以它的效率其实和Vector是一样的,这个也在我们后面讲到的subList()源码里面得到印证,不信,我们在代码里面测试一下:
[java]
view plain
copy
print
?
- /**
- * 测试使用Collections.synchronizedList调用增、删、改三个API操作50000个数据,求100次的平均时间
- *
- */
- public class QTest {
- public static void main(String[] args) {
- long totalTime = 0;
- for (int i = 0; i < 100; i++) {
- totalTime += new QTest().getTime();
- }
- System.out.println(“Collections.synchronizedList() 平均耗时:” + (totalTime / 100));
- }
- public long getTime() {
- List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>());
- long startTime = System.currentTimeMillis();
- for (int i = 0; i < 50000; i++) {
- list.add(i * 10); // 增加
- }
- for (int i = 0; i < 50000; i++) { // 修改
- list.set(i, i);
- }
- for (int i = 0; i < list.size(); i++) { // 删除
- list.remove(i);
- }
- long endTime = System.currentTimeMillis();
- System.out.println(“Collections.synchronizedList()消耗时间:” + (endTime – startTime));
- return endTime – startTime;
- }
- }
/**
* 测试使用Collections.synchronizedList调用增、删、改三个API操作50000个数据,求100次的平均时间
*
*/
public class QTest {
public static void main(String[] args) {
long totalTime = 0;
for (int i = 0; i < 100; i++) {
totalTime += new QTest().getTime();
}
System.out.println("Collections.synchronizedList() 平均耗时:" + (totalTime / 100));
}
public long getTime() {
List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>());
long startTime = System.currentTimeMillis();
for (int i = 0; i < 50000; i++) {
list.add(i * 10); // 增加
}
for (int i = 0; i < 50000; i++) { // 修改
list.set(i, i);
}
for (int i = 0; i < list.size(); i++) { // 删除
list.remove(i);
}
long endTime = System.currentTimeMillis();
System.out.println("Collections.synchronizedList()消耗时间:" + (endTime - startTime));
return endTime - startTime;
}
}
[java]
view plain
copy
print
?
- /**
- * 测试使用Vector调用增、删、改三个API操作50000个数据,求100次的平均时间
- *
- */
- public class PTest {
- public static void main(String[] args) {
- long totalTime = 0;
- for (int i = 0; i < 100; i++) {
- totalTime += new QTest().getTime();
- }
- System.out.println(“vector 平均耗时:” + (totalTime / 100));
- }
- public long getTime() {
- Vector<Integer> vector = new Vector<>();
- long nStartTime = System.currentTimeMillis();
- for (int i = 0; i < 100000; i++) {
- vector.add(i * 10); // 增加
- }
- for (int i = 0; i < 100000; i++) { // 修改
- vector.set(i, i);
- }
- for (int i = 0; i < vector.size(); i++) { // 删除
- vector.remove(i);
- }
- long nEndTime = System.currentTimeMillis();
- System.out.println(“vector消耗时间:” + (nEndTime – nStartTime));
- return nEndTime – nStartTime;
- }
- }
/**
* 测试使用Vector调用增、删、改三个API操作50000个数据,求100次的平均时间
*
*/
public class PTest {
public static void main(String[] args) {
long totalTime = 0;
for (int i = 0; i < 100; i++) {
totalTime += new QTest().getTime();
}
System.out.println("vector 平均耗时:" + (totalTime / 100));
}
public long getTime() {
Vector<Integer> vector = new Vector<>();
long nStartTime = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
vector.add(i * 10); // 增加
}
for (int i = 0; i < 100000; i++) { // 修改
vector.set(i, i);
}
for (int i = 0; i < vector.size(); i++) { // 删除
vector.remove(i);
}
long nEndTime = System.currentTimeMillis();
System.out.println("vector消耗时间:" + (nEndTime - nStartTime));
return nEndTime - nStartTime;
}
}
这两段代码其实就是对同步的ArrayList进行增、删、改50000条数据,并重复100次,求平均时间。通过运行,在我的电脑(每台电脑的运行速度不一样)里Collections.synchronizedList的100次平均消耗时间是:129ms,而Vector的100次平均消耗时间是:130ms。在需要考虑线程安全时,你是用Vector和Collections.synchronizedList初始化的ArrayList大概效率是差不多的。所以,Vector也并非毫无用武之地,那么这次我们就一起探究一下Vector的源码。
三、源码解读
1. 继承、实现
extends:AbstractList<E> implements:List<E>, RandomAccess, Cloneable, java.io.Serializable
2. 全局变量
(1) 存放数据的数组
[java]
view plain
copy
print
?
- protected Object[] elementData;
protected Object[] elementData;
(2) 存放数量
[java]
view plain
copy
print
?
- protected int elementCount;
protected int elementCount;
(3) 容量增量
[java]
view plain
copy
print
?
- protected int capacityIncrement;
protected int capacityIncrement;
3. 构造方法
(1) 不带参数的构造方法
[java]
view plain
copy
print
?
- public Vector() {
- this(10);
- }
public Vector() {
this(10);
}
(2) 带初始化容量大小的构造方法
[java]
view plain
copy
print
?
- /**
- * @param initialCapacity 初始化容量大小
- */
- public Vector(int initialCapacity) {
- this(initialCapacity, 0);
- }
/**
* @param initialCapacity 初始化容量大小
*/
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
(3) 带初始化容量和容量增量的构造方法
[java]
view plain
copy
print
?
- /**
- * @param initialCapacity 初始化容量大小
- * @param capacityIncrement 容量增量
- */
- public Vector(int initialCapacity, int capacityIncrement) {
- super();
- if (initialCapacity < 0)
- throw new IllegalArgumentException(“Illegal Capacity: “+
- initialCapacity);
- this.elementData = new Object[initialCapacity];
- this.capacityIncrement = capacityIncrement;
- }
/**
* @param initialCapacity 初始化容量大小
* @param capacityIncrement 容量增量
*/
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
(4) 带Colleciton参数的构造方法
[java]
view plain
copy
print
?
- /**
- * @param c 将c转为Vector
- */
- 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)
- elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
- }
/**
* @param c 将c转为Vector
*/
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)
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}
4. 方法
(1) public synchronized void copyInto(Object[] anArray) 源码解释: 通过JNI调用c++库的arraycopy方法,实现将anArray数组复制到当前的Vector。
[java]
view plain
copy
print
?
- public synchronized void copyInto(Object[] anArray) {
- System.arraycopy(elementData, 0, anArray, 0, elementCount);
- }
public synchronized void copyInto(Object[] anArray) {
System.arraycopy(elementData, 0, anArray, 0, elementCount);
}
(2) public synchronized void trimToSize() 源码解释: 用以优化Vector的内存,我们都知道,Vector的每次容量增量是当前大小的2倍,但是当我们没法用完申请的这么多内存时,我们可以通过调用这个方法用以将不需要的内存释放掉。
[java]
view plain
copy
print
?
- public synchronized void trimToSize() {
- modCount++; // 修改次数增加
- int oldCapacity = elementData.length; // 获取到当前的申请的内存大小
- if (elementCount < oldCapacity) { // 如果当前存放的数量比申请的内存要少
- elementData = Arrays.copyOf(elementData, elementCount); // 重新为这个数组申请elementCount大小内存,并存放这些数据
- }
- }
public synchronized void trimToSize() {
modCount++; // 修改次数增加
int oldCapacity = elementData.length; // 获取到当前的申请的内存大小
if (elementCount < oldCapacity) { // 如果当前存放的数量比申请的内存要少
elementData = Arrays.copyOf(elementData, elementCount); // 重新为这个数组申请elementCount大小内存,并存放这些数据
}
}
(3) public synchronized void ensureCapacity(int minCapacity) 源码解释: 当要扩容时,会调用此方法,保证当前容量能存放得下所需要存放的元素数量。如果不够时,会调用grow()方法进行扩容。
[java]
view plain
copy
print
?
- public synchronized void ensureCapacity(int minCapacity) {
- if (minCapacity > 0) {
- modCount++;
- ensureCapacityHelper(minCapacity);
- }
- }
public synchronized void ensureCapacity(int minCapacity) {
if (minCapacity > 0) {
modCount++;
ensureCapacityHelper(minCapacity);
}
}
[java]
view plain
copy
print
?
- private void ensureCapacityHelper(int minCapacity) {
- // overflow-conscious code
- if (minCapacity – elementData.length > 0)
- grow(minCapacity); // 如果当前容量比数组的长度要小时,调用grow扩容
- }
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity); // 如果当前容量比数组的长度要小时,调用grow扩容
}
[java]
view plain
copy
print
?
- private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE – 8;
- /**
- * Vector的扩容方法, 每次扩容至2倍
- * @param minCapacity
- */
- private void grow(int minCapacity) {
- // overflow-conscious code
- int oldCapacity = elementData.length; // 获取到数组的长度
- int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); //如果没有初始化capacityIncrement,则增加至两倍
- if (newCapacity – minCapacity < 0)
- newCapacity = minCapacity;
- if (newCapacity – MAX_ARRAY_SIZE > 0) // 如果扩容后的容量超过了最大容量
- newCapacity = hugeCapacity(minCapacity); // 调用hugeCapacity方法
- elementData = Arrays.copyOf(elementData, newCapacity); // 将数组复制到扩容后的新内存中去
- }
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* Vector的扩容方法, 每次扩容至2倍
* @param minCapacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; // 获取到数组的长度
int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); //如果没有初始化capacityIncrement,则增加至两倍
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0) // 如果扩容后的容量超过了最大容量
newCapacity = hugeCapacity(minCapacity); // 调用hugeCapacity方法
elementData = Arrays.copyOf(elementData, newCapacity); // 将数组复制到扩容后的新内存中去
}
[java]
view plain
copy
print
?
- private static int hugeCapacity(int minCapacity) {
- if (minCapacity < 0) // overflow
- throw new OutOfMemoryError();
- return (minCapacity > MAX_ARRAY_SIZE) ?
- Integer.MAX_VALUE :
- MAX_ARRAY_SIZE;
- }
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
(4) public synchronized void setSize(int newSize) 源码解释: 修改容量,当newSize比数组的长度要大时,将其复制到新的内存区域,如果要小的话,则从newSize位置到数组的最后一个位置的所有元素置为空。
[java]
view plain
copy
print
?
- public synchronized void setSize(int newSize) {
- modCount++;
- if (newSize > elementCount) {
- ensureCapacityHelper(newSize);
- } else {
- for (int i = newSize ; i < elementCount ; i++) {
- elementData[i] = null;
- }
- }
- elementCount = newSize;
- }
public synchronized void setSize(int newSize) {
modCount++;
if (newSize > elementCount) {
ensureCapacityHelper(newSize);
} else {
for (int i = newSize ; i < elementCount ; i++) {
elementData[i] = null;
}
}
elementCount = newSize;
}
(5) public synchronized int capacity() 源码解释: 返回数组长度,即申请内存的长度。
[java]
view plain
copy
print
?
- public synchronized int capacity() {
- return elementData.length;
- }
public synchronized int capacity() {
return elementData.length;
}
(6) public synchronized int size() 源码解释: 返回数组已经使用的长度,即存放的数据个数。
[java]
view plain
copy
print
?
- public synchronized int size() {
- return elementCount;
- }
public synchronized int size() {
return elementCount;
}
(7) public synchronized boolean isEmpty() 源码解释: 判空,如果数量为0,即为empty。
[java]
view plain
copy
print
?
- public synchronized boolean isEmpty() {
- return elementCount == 0;
- }
public synchronized boolean isEmpty() {
return elementCount == 0;
}
(8) public Enumeration<E> elements() 源码解释: 返回一个Enumeration对象的序列。Enumeration只有两个方法,hasMoreElements()和nextElement(),它只能从首个元素遍历到最后一个元素,并不能根据位置拿到具体的元素。
[java]
view plain
copy
print
?
- public Enumeration<E> elements() {
- return new Enumeration<E>() {
- int count = 0;
- public boolean hasMoreElements() {
- return count < elementCount;
- }
- public E nextElement() {
- synchronized (Vector.this) {
- if (count < elementCount) {
- return elementData(count++);
- }
- }
- throw new NoSuchElementException( “Vector Enumeration”);
- }
- };
- }
public Enumeration<E> elements() {
return new Enumeration<E>() {
int count = 0;
public boolean hasMoreElements() {
return count < elementCount;
}
public E nextElement() {
synchronized (Vector.this) {
if (count < elementCount) {
return elementData(count++);
}
}
throw new NoSuchElementException("Vector Enumeration");
}
};
}
(9) public boolean contains(Object o) 源码解释: 是否包含对象o。调用indexOf判断是否存在。
[java]
view plain
copy
print
?
- public boolean contains(Object o) {
- return indexOf(o, 0) >= 0;
- }
public boolean contains(Object o) {
return indexOf(o, 0) >= 0;
}
[java]
view plain
copy
print
?
- public int indexOf(Object o) {
- return indexOf(o, 0);
- }
public int indexOf(Object o) {
return indexOf(o, 0);
}
(10) public synchronized int indexOf(Object o, int index) 源码解释: 判断o是否为空,如果为空,则遍历是否存在值为空的元素;不为空,判断是否存在和o相等的元素。
[java]
view plain
copy
print
?
- public synchronized int indexOf(Object o, int index) {
- if (o == null) {
- for (int i = index ; i < elementCount ; i++)
- if (elementData[i]==null)
- return i;
- } else {
- for (int i = index ; i < elementCount ; i++)
- if (o.equals(elementData[i]))
- return i;
- }
- return –1;
- }
public synchronized int indexOf(Object o, int index) {
if (o == null) {
for (int i = index ; i < elementCount ; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = index ; i < elementCount ; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
(11) public synchronized int lastIndexOf 源码解释: 获取该元素所处的最后一个位置,不存在则返回-1
[java]
view plain
copy
print
?
- public synchronized int lastIndexOf(Object o) {
- return lastIndexOf(o, elementCount-1);
- }
public synchronized int lastIndexOf(Object o) {
return lastIndexOf(o, elementCount-1);
}
[java]
view plain
copy
print
?
- public synchronized int lastIndexOf(Object o, int index) {
- if (index >= elementCount)
- throw new IndexOutOfBoundsException(index + ” >= “+ elementCount);
- if (o == null) {
- for (int i = index; i >= 0; i–)
- if (elementData[i]==null)
- return i;
- } else {
- for (int i = index; i >= 0; i–)
- if (o.equals(elementData[i]))
- return i;
- }
- return –1;
- }
public synchronized int lastIndexOf(Object o, int index) {
if (index >= elementCount)
throw new IndexOutOfBoundsException(index + " >= "+ elementCount);
if (o == null) {
for (int i = index; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = index; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
(12) public synchronized E elementAt(int index)
源码解释: 返回这个位置的元素。其实就是判断数组的index位置是否有元素
[java]
view plain
copy
print
?
- public synchronized E elementAt(int index) {
- if (index >= elementCount) {
- throw new ArrayIndexOutOfBoundsException(index + ” >= “ + elementCount);
- }
- return elementData(index);
- }
public synchronized E elementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
}
return elementData(index);
}
[java]
view plain
copy
print
?
- E elementData(int index) {
- return (E) elementData[index];
- }
E elementData(int index) {
return (E) elementData[index];
}
(13) public synchronized E firstElement() 源码解释: 返回数组第0个位置的元素。
[java]
view plain
copy
print
?
- public synchronized E firstElement() {
- if (elementCount == 0) {
- throw new NoSuchElementException();
- }
- return elementData(0);
- }
public synchronized E firstElement() {
if (elementCount == 0) {
throw new NoSuchElementException();
}
return elementData(0);
}
(14) public synchronized E lastElement() 源码解释: 返回数组最后一个位置的元素。
[java]
view plain
copy
print
?
- public synchronized E lastElement() {
- if (elementCount == 0) {
- throw new NoSuchElementException();
- }
- return elementData(elementCount – 1);
- }
public synchronized E lastElement() {
if (elementCount == 0) {
throw new NoSuchElementException();
}
return elementData(elementCount - 1);
}
(15) public synchronized void setElementAt(E obj, int index) 源码解释: 修改第index位置的值为obj。其实就是数组赋值。
[java]
view plain
copy
print
?
- public synchronized void setElementAt(E obj, int index) {
- if (index >= elementCount) {
- throw new ArrayIndexOutOfBoundsException(index + ” >= “ +
- elementCount);
- }
- elementData[index] = obj;
- }
public synchronized void setElementAt(E obj, int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
elementData[index] = obj;
}
(16) public synchronized void removeElementAt(int index) 源码解释:
获取到index位置后有多少个元素,并将index位置后面的元素复制到index位置前的后面,再将index位置置空。复制操作通过JNI实现。
[java]
view plain
copy
print
?
- 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; // 获取第index位置后有多少个元素
- if (j > 0) {
- System.arraycopy(elementData, index + 1, elementData, index, j); // 将emlementData[j, elementCount]复制到elementData[0, index]的后面
- }
- elementCount–;
- elementData[elementCount] = null; // 等待GC
- }
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; // 获取第index位置后有多少个元素
if (j > 0) {
System.arraycopy(elementData, index + 1, elementData, index, j); // 将emlementData[j, elementCount]复制到elementData[0, index]的后面
}
elementCount--;
elementData[elementCount] = null; // 等待GC
}
(17) public synchronized void insertElementAt(E obj, int index) 源码解释: 将index位置后的元素复制到原数组的index+1位置后的地方,并在index位置赋值obj。
[java]
view plain
copy
print
?
- 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+1, elementCount]复制到elementData[index+1, elementCount +1]位置,
- elementData[index] = obj; // 在index位置赋值obj
- elementCount++;
- }
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+1, elementCount]复制到elementData[index+1, elementCount +1]位置,
elementData[index] = obj; // 在index位置赋值obj
elementCount++;
}
(18) public synchronized void addElement(E obj) 源码解释: 在数组最后添加数据obj。先扩容,再通过数组赋值。
[java]
view plain
copy
print
?
- public synchronized void addElement(E obj) {
- modCount++;
- ensureCapacityHelper(elementCount + 1);
- elementData[elementCount++] = obj;
- }
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
(19) public synchronized boolean removeElement(Object obj) 源码解释: 移除元素。先获取到移除元素在数组的位置,然后调用removeElementAt方法移除元素。
[java]
view plain
copy
print
?
- public synchronized boolean removeElement(Object obj) {
- modCount++;
- int i = indexOf(obj);
- if (i >= 0) {
- removeElementAt(i);
- return true;
- }
- return false;
- }
public synchronized boolean removeElement(Object obj) {
modCount++;
int i = indexOf(obj);
if (i >= 0) {
removeElementAt(i);
return true;
}
return false;
}
(20) public synchronized void removeAllElements() 源码解释: 移除所有元素。即将所有元素置为null,等待gc。
[java]
view plain
copy
print
?
- public synchronized void removeAllElements() {
- modCount++;
- // Let gc do its work
- for (int i = 0; i < elementCount; i++)
- elementData[i] = null;
- elementCount = 0;
- }
public synchronized void removeAllElements() {
modCount++;
// Let gc do its work
for (int i = 0; i < elementCount; i++)
elementData[i] = null;
elementCount = 0;
}
(21) public synchronized E get(int index) 源码解释: 获取index位置的元素。
[java]
view plain
copy
print
?
- public synchronized E get(int index) {
- if (index >= elementCount)
- throw new ArrayIndexOutOfBoundsException(index);
- return elementData(index);
- }
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
return elementData(index);
}
(22) public synchronized E set(int index, E element) 源码解释: 修改index位置的值为element。实现原理也是直接数组赋值。
[java]
view plain
copy
print
?
- public synchronized E set(int index, E element) {
- if (index >= elementCount)
- throw new ArrayIndexOutOfBoundsException(index);
- E oldValue = elementData(index);
- elementData[index] = element;
- return oldValue;
- }
public synchronized E set(int index, E element) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
(23) public synchronized boolean add(E e) 源码解释: 在最后位置新增元素e。先判断是否需要扩容,然后赋值。实现原理和addElement是一样的。
[java]
view plain
copy
print
?
- public synchronized boolean add(E e) {
- modCount++;
- ensureCapacityHelper(elementCount + 1);
- elementData[elementCount++] = e;
- return true;
- }
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
(24) public boolean remove(Object o) 源码解释: 移除元素,和removeElement方法一样。
[java]
view plain
copy
print
?
- public boolean remove(Object o) {
- return removeElement(o);
- }
public boolean remove(Object o) {
return removeElement(o);
}
(25) public void add(int index, E element) 源码解释: 添加元素,和insertElementAt方法一样。
[java]
view plain
copy
print
?
- public void add(int index, E element) {
- insertElementAt(element, index);
- }
public void add(int index, E element) {
insertElementAt(element, index);
}
(26) public synchronized E remove(int index) 源码解释: 移除index位置的元素。实现思路和removeElementAt类似。
[java]
view plain
copy
print
?
- public synchronized E remove(int index) {
- modCount++;
- if (index >= elementCount)
- throw new ArrayIndexOutOfBoundsException(index);
- E oldValue = elementData(index); // 获取到旧值
- int numMoved = elementCount – index – 1; // index位置后面元素的个数
- if (numMoved > 0)
- System.arraycopy(elementData, index+1, elementData, index, numMoved); // 将elementData[index+1, elementCount]移到element[0, index]后
- elementData[–elementCount] = null; // Let gc do its work
- return oldValue;
- }
public synchronized E remove(int index) {
modCount++;
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index); // 获取到旧值
int numMoved = elementCount - index - 1; // index位置后面元素的个数
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved); // 将elementData[index+1, elementCount]移到element[0, index]后
elementData[--elementCount] = null; // Let gc do its work
return oldValue;
}
(27) public void clear() 源码解释: 移除所有元素,直接调用removeAllElements()。
[java]
view plain
copy
print
?
- public void clear() {
- removeAllElements();
- }
public void clear() {
removeAllElements();
}
(28) public synchronized boolean containsAll(Collection<?> c) 源码解释: 判断是否包含集合c的所有元素。调用AbstractCollection的实现,代码也很简单,不赘叙。
[java]
view plain
copy
print
?
- public synchronized boolean containsAll(Collection<?> c) {
- return super.containsAll(c);
- }
public synchronized boolean containsAll(Collection<?> c) {
return super.containsAll(c);
}
[java]
view plain
copy
print
?
- public boolean containsAll(Collection<?> c) {
- for (Object e : c)
- if (!contains(e))
- return false;
- return true;
- }
public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}
(29) public synchronized boolean addAll(Collection<? extends E> c) 源码解释: 把集合c复制到当前数组的末尾。先判断是否需要扩容,然后调用JNI的arraycopy实现复制。
[java]
view plain
copy
print
?
- public synchronized boolean addAll(Collection<? extends E> c) {<pre name=“code” class=“java”> modCount++;</pre> Object[] a = c.toArray(); int numNew = a.length; ensureCapacityHelper(elementCount + numNew); System.arraycopy(a, 0, elementData, elementCount, numNew); elementCount += numNew; return numNew != 0; }
- <pre></pre>
- <br>
- (30) public synchronized boolean removeAll(Collection<?> c)
public synchronized boolean addAll(Collection<? extends E> c) { [java] view plain copy print ?
源码解释: 将包含集合c的所有元素移除。调用AbstractCollection的实现,代码也很简单,不赘叙。
- modCount++;
modCount++;Object[] a = c.toArray(); int numNew = a.length; ensureCapacityHelper(elementCount + numNew); System.arraycopy(a, 0, elementData, elementCount, numNew); elementCount += numNew; return numNew != 0; }
(30) public synchronized boolean removeAll(Collection<?> c)
[java]
view plain
copy
?
- public boolean removeAll(Collection<?> c) {
- Objects.requireNonNull(c);
- boolean modified = false;
- Iterator<?> it = iterator();
- while (it.hasNext()) {
- if (c.contains(it.next())) {
- it.remove();
- modified = true;
- }
- }
- return modified;
- }
public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); boolean modified = false; Iterator<?> it = iterator(); while (it.hasNext()) { if (c.contains(it.next())) { it.remove(); modified = true; } } return modified; }
(31) public synchronized boolean retainAll(Collection<?> c) 源码解释: 将数组中不是c中包含的元素全部移除。调用AbstractCollection的实现,代码也很简单,不赘叙。
[java]
view plain
copy
?
- public synchronized boolean retainAll(Collection<?> c) {
- return super.retainAll(c);
- }
public synchronized boolean retainAll(Collection<?> c) { return super.retainAll(c); }
[java]
view plain
copy
?
- public boolean retainAll(Collection<?> c) {
- Objects.requireNonNull(c);
- boolean modified = false;
- Iterator<E> it = iterator();
- while (it.hasNext()) {
- if (!c.contains(it.next())) {
- it.remove();
- modified = true;
- }
- }
- return modified;
- }
public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); boolean modified = false; Iterator<E> it = iterator(); while (it.hasNext()) { if (!c.contains(it.next())) { it.remove(); modified = true; } } return modified; }
(32) public synchronized boolean addAll(int index, Collection<? extends E> c)
源码解释: 在index位置插入集合c。实现原理和在某个位置插入元素原理一样,不赘叙。
[java]
view plain
copy
?
- 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;
- return numNew != 0;
- }
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; return numNew != 0; }
(33) public synchronized List<E> subList(int fromIndex, int toIndex) 源码解释: 调用父类的subList,然后通过Collections.synchronizedList来保证子List是同步的,这也就印证了我们前面所说的Collections.synchronizedList初始化的ArrayList和Vector是一样效率的,因为它们的同步方式都是一样的,而增删改查这些操作对于它们两个来说都是一样的原理,所以可以知道它们的效率是一样的。
[java]
view plain
copy
?
- public synchronized List<E> subList(int fromIndex, int toIndex) {
- return Collections.synchronizedList(super.subList(fromIndex, toIndex),
- this);
- }
public synchronized List<E> subList(int fromIndex, int toIndex) { return Collections.synchronizedList(super.subList(fromIndex, toIndex), this); }
(34) protected synchronized void removeRange(int fromIndex, int toIndex) 源码解释: 将某个范围的数据移除。实现原理和删除某个位置的元素原理是一样的,不赘叙。
[java]
view plain
copy
?
- protected synchronized void removeRange(int fromIndex, int toIndex) {
- modCount++;
- int numMoved = elementCount - toIndex;
- System.arraycopy(elementData, toIndex, elementData, fromIndex,
- numMoved);
- // Let gc do its work
- int newElementCount = elementCount - (toIndex-fromIndex);
- while (elementCount != newElementCount)
- elementData[--elementCount] = null;
- }
protected synchronized void removeRange(int fromIndex, int toIndex) { modCount++; int numMoved = elementCount - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); // Let gc do its work int newElementCount = elementCount - (toIndex-fromIndex); while (elementCount != newElementCount) elementData[--elementCount] = null; }
(35) public synchronized ListIterator<E> listIterator(int index) 源码解释: 返回一个从index位置开始的LIstIterator,方便我们遍历Vector,关于ListIterator在
《Java容器类源码-LinkedList的最全的源码分析》已经详说,这里不赘叙。
[java]
view plain
copy
?
- public synchronized ListIterator<E> listIterator(int index) {
- if (index < 0 || index > elementCount)
- throw new IndexOutOfBoundsException( "Index: "+index);
- return new ListItr(index);
- }
public synchronized ListIterator<E> listIterator(int index) { if (index < 0 || index > elementCount) throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index); }
(36) public synchronized ListIterator<E> listIterator() 源码解释: 返回一个从0位置开始的ListIterator,不赘叙。
[java]
view plain
copy
?
- public synchronized ListIterator<E> listIterator() {
- return new ListItr(0);
- }
public synchronized ListIterator<E> listIterator() { return new ListItr(0); }
(37) public synchronized Iterator<E> iterator() 源码解释: 返回一个Iterator实现类Itr。有人会问ListIterator和Itr有什么区别吗?其实ListIterator是Itr的子类,它在Itr的基础上再增加了一些接口,例如hasPrevious(),nextIndex()等,所以如果觉得Iterator不能满足你的需求,可以看一下ListIterator里面提供的API。
[java]
view plain
copy
?
- public synchronized Iterator<E> iterator() {
- return new Itr();
- }
public synchronized Iterator<E> iterator() { return new Itr(); }
(38) public Spliterator<E> spliterator() 源码解释: 实例化一个VectorSpliterator对象,并返回。VectorSpliterator是JDK1.8之后LinkedList新增的内部类,因为用得比较少,我就不在这里班门弄斧了,大家有需要可以自行深入研究。
[java]
view plain
copy
?
- public Spliterator<E> spliterator() {
- return new VectorSpliterator<>(this, null, 0, -1, 0);
- }
public Spliterator<E> spliterator() { return new VectorSpliterator<>(this, null, 0, -1, 0); }
四、总结
看完了Vector的源码,我觉得我们需要学到比较重要的几点。首先是开头所说的Vector和ArrayList的区别,这里就不重复了。第二个就是我们通过subList这个实现可以看到,它的子序列其实也是通过Collections.synchronizedList来初始化子序列并返回的,所以其实Collections.synchronizedList初始化的ArrayList实现同步的原理和Vector是一样的,而ArrayList和Vector的底层都是数组,常规的增删改查操作是一样的,所以我们可以确定Vector和实现了同步的ArrayList在数据操作时的效率是相近的,所以我觉得我们并不需要纠结在考虑线程安全时到底是用Collections.synchronizedList初始化的ArrayList还是Vector。第三个就是需要了解到Vector的增删改查实现原理,它的api核心可以说就是这几个方法了,所有其他api都是围绕这几个方法来进行扩展。