Java容器类源码-Vector的最全的源码分析

一、概述

我们都知道,在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
?

  1. /** 
  2.  * 测试使用Collections.synchronizedList调用增、删、改三个API操作50000个数据,求100次的平均时间 
  3.  * 
  4.  */  
  5. public class QTest {  
  6.     public static void main(String[] args) {  
  7.           
  8.         long totalTime = 0;  
  9.           
  10.         for (int i = 0; i <  100; i++) {  
  11.             totalTime += new QTest().getTime();  
  12.         }  
  13.           
  14.         System.out.println(“Collections.synchronizedList() 平均耗时:” + (totalTime / 100));  
  15.   
  16.     }  
  17.   
  18.     public long getTime() {  
  19.           
  20.         List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>());  
  21.           
  22.         long startTime = System.currentTimeMillis();  
  23.           
  24.         for (int i = 0; i <  50000; i++) {  
  25.             list.add(i * 10); // 增加  
  26.         }  
  27.         for (int i = 0; i <  50000; i++) { // 修改  
  28.             list.set(i, i);  
  29.         }  
  30.         for (int i = 0; i < list.size(); i++) {  // 删除  
  31.             list.remove(i);  
  32.         }  
  33.           
  34.         long endTime = System.currentTimeMillis();  
  35.           
  36.         System.out.println(“Collections.synchronizedList()消耗时间:” + (endTime – startTime));  
  37.           
  38.         return endTime – startTime;  
  39.     }  
  40. }  
/**
 * 测试使用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
?

  1. /** 
  2.  * 测试使用Vector调用增、删、改三个API操作50000个数据,求100次的平均时间 
  3.  * 
  4.  */  
  5. public class PTest {  
  6.     public static void main(String[] args) {  
  7.   
  8.         long totalTime = 0;  
  9.   
  10.         for (int i = 0; i <  100; i++) {  
  11.             totalTime += new QTest().getTime();  
  12.         }  
  13.   
  14.         System.out.println(“vector 平均耗时:” + (totalTime / 100));  
  15.     }  
  16.   
  17.     public long getTime() {  
  18.         Vector<Integer> vector = new Vector<>();  
  19.           
  20.         long nStartTime = System.currentTimeMillis();  
  21.           
  22.         for (int i = 0; i <  100000; i++) {  
  23.             vector.add(i * 10); // 增加  
  24.         }  
  25.         for (int i = 0; i <  100000; i++) { // 修改  
  26.             vector.set(i, i);  
  27.         }  
  28.         for (int i = 0; i < vector.size(); i++) {  // 删除  
  29.             vector.remove(i);  
  30.         }  
  31.           
  32.         long nEndTime = System.currentTimeMillis();  
  33.           
  34.         System.out.println(“vector消耗时间:” + (nEndTime – nStartTime));  
  35.           
  36.         return nEndTime – nStartTime;  
  37.     }  
  38. }  
/**
 * 测试使用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
?

  1. protected Object[] elementData;  
protected Object[] elementData;

(2) 存放数量

[java]
view plain
copy
print
?

  1. protected int elementCount;  
protected int elementCount;

(3) 容量增量

[java]
view plain
copy
print
?

  1. protected int capacityIncrement;  
protected int capacityIncrement;

3. 构造方法

(1) 不带参数的构造方法

[java]
view plain
copy
print
?

  1. public Vector() {  
  2.     this(10);  
  3. }  
public Vector() {
    this(10);
}

(2) 带初始化容量大小的构造方法

[java]
view plain
copy
print
?

  1. /** 
  2.  * @param initialCapacity 初始化容量大小 
  3.  */  
  4. public Vector(int initialCapacity) {  
  5.     this(initialCapacity, 0);  
  6. }  
/**
 * @param initialCapacity 初始化容量大小
 */
public Vector(int initialCapacity) {
    this(initialCapacity, 0);
}

(3) 带初始化容量和容量增量的构造方法

[java]
view plain
copy
print
?

  1. /** 
  2.  * @param initialCapacity   初始化容量大小 
  3.  * @param capacityIncrement 容量增量 
  4.  */  
  5. public Vector(int initialCapacity, int capacityIncrement) {  
  6.     super();  
  7.     if (initialCapacity < 0)  
  8.         throw new IllegalArgumentException(“Illegal Capacity: “+  
  9.                                            initialCapacity);  
  10.     this.elementData = new Object[initialCapacity];  
  11.     this.capacityIncrement = capacityIncrement;  
  12. }  
/**
 * @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
?

  1. /** 
  2.  * @param c 将c转为Vector 
  3.  */  
  4. public Vector(Collection<? extends E> c) {  
  5.     elementData = c.toArray();  
  6.     elementCount = elementData.length;  
  7.     // c.toArray might (incorrectly) not return Object[] (see 6260652)  
  8.     if (elementData.getClass() != Object[].class)  
  9.         elementData = Arrays.copyOf(elementData, elementCount, Object[].class);  
  10. }  
/**
 * @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
?

  1. public synchronized void copyInto(Object[] anArray) {  
  2.     System.arraycopy(elementData, 0, anArray, 0, elementCount);  
  3. }  
    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
?

  1. public synchronized void trimToSize() {  
  2.     modCount++;     // 修改次数增加  
  3.     int oldCapacity = elementData.length;   // 获取到当前的申请的内存大小  
  4.     if (elementCount < oldCapacity) {        // 如果当前存放的数量比申请的内存要少  
  5.         elementData = Arrays.copyOf(elementData, elementCount); // 重新为这个数组申请elementCount大小内存,并存放这些数据  
  6.     }  
  7. }  
    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
?

  1. public synchronized void ensureCapacity(int minCapacity) {  
  2.     if (minCapacity > 0) {  
  3.         modCount++;  
  4.         ensureCapacityHelper(minCapacity);  
  5.     }  
  6. }  
    public synchronized void ensureCapacity(int minCapacity) {
        if (minCapacity > 0) {
            modCount++;
            ensureCapacityHelper(minCapacity);
        }
    }

[java]
view plain
copy
print
?

  1. private void ensureCapacityHelper(int minCapacity) {  
  2.     // overflow-conscious code  
  3.     if (minCapacity – elementData.length > 0)  
  4.         grow(minCapacity);  // 如果当前容量比数组的长度要小时,调用grow扩容  
  5. }  
    private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);	// 如果当前容量比数组的长度要小时,调用grow扩容
    }

[java]
view plain
copy
print
?

  1. private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE –  8;  
  2.     /** 
  3.      * Vector的扩容方法, 每次扩容至2倍 
  4.      * @param minCapacity 
  5.      */  
  6.     private void grow(int minCapacity) {  
  7.         // overflow-conscious code  
  8.         int oldCapacity = elementData.length;   // 获取到数组的长度  
  9.         int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);  //如果没有初始化capacityIncrement,则增加至两倍  
  10.         if (newCapacity – minCapacity < 0)     
  11.             newCapacity = minCapacity;  
  12.         if (newCapacity – MAX_ARRAY_SIZE > 0)     // 如果扩容后的容量超过了最大容量  
  13.             newCapacity = hugeCapacity(minCapacity);    // 调用hugeCapacity方法  
  14.         elementData = Arrays.copyOf(elementData, newCapacity);  // 将数组复制到扩容后的新内存中去  
  15.     }  
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
?

  1. private static int hugeCapacity(int minCapacity) {    
  2.     if (minCapacity < 0// overflow  
  3.         throw new OutOfMemoryError();  
  4.     return (minCapacity > MAX_ARRAY_SIZE) ?  
  5.         Integer.MAX_VALUE :  
  6.         MAX_ARRAY_SIZE;  
  7. }  
    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
?

  1. public synchronized void setSize(int newSize) {  
  2.     modCount++;  
  3.     if (newSize > elementCount) {  
  4.         ensureCapacityHelper(newSize);  
  5.     } else {  
  6.         for (int i = newSize ; i < elementCount ; i++) {  
  7.             elementData[i] = null;  
  8.         }  
  9.     }  
  10.     elementCount = newSize;  
  11. }  
    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
?

  1. public synchronized int capacity() {  
  2.     return elementData.length;  
  3. }  
    public synchronized int capacity() {
        return elementData.length;
    }

(6) public synchronized int size() 源码解释: 返回数组已经使用的长度,即存放的数据个数。
[java]
view plain
copy
print
?

  1. public synchronized int size() {  
  2.     return elementCount;  
  3. }  
    public synchronized int size() {
        return elementCount;
    }

(7) public synchronized boolean isEmpty() 源码解释: 判空,如果数量为0,即为empty。
[java]
view plain
copy
print
?

  1. public synchronized boolean isEmpty() {  
  2.     return elementCount == 0;  
  3. }  
    public synchronized boolean isEmpty() {
        return elementCount == 0;
    }

(8) public Enumeration<E> elements() 源码解释: 返回一个Enumeration对象的序列。Enumeration只有两个方法,hasMoreElements()和nextElement(),它只能从首个元素遍历到最后一个元素,并不能根据位置拿到具体的元素。
[java]
view plain
copy
print
?

  1. public Enumeration<E> elements() {  
  2.     return new Enumeration<E>() {  
  3.         int count = 0;  
  4.   
  5.         public boolean hasMoreElements() {  
  6.             return count < elementCount;  
  7.         }  
  8.   
  9.         public E nextElement() {  
  10.             synchronized (Vector.this) {  
  11.                 if (count < elementCount) {  
  12.                     return elementData(count++);  
  13.                 }  
  14.             }  
  15.             throw new NoSuchElementException( “Vector Enumeration”);  
  16.         }  
  17.     };  
  18. }  
    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
?

  1. public boolean contains(Object o) {  
  2.     return indexOf(o, 0) >= 0;  
  3. }  
    public boolean contains(Object o) {
        return indexOf(o, 0) >= 0;
    }

[java]
view plain
copy
print
?

  1. public int indexOf(Object o) {  
  2.     return indexOf(o, 0);  
  3. }  
    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
?

  1. public synchronized int indexOf(Object o, int index) {  
  2.     if (o == null) {  
  3.         for (int i = index ; i < elementCount ; i++)  
  4.             if (elementData[i]==null)  
  5.                 return i;  
  6.     } else {  
  7.         for (int i = index ; i < elementCount ; i++)  
  8.             if (o.equals(elementData[i]))  
  9.                 return i;  
  10.     }  
  11.     return –1;  
  12. }  
    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
?

  1. public synchronized int lastIndexOf(Object o) {  
  2.     return lastIndexOf(o, elementCount-1);  
  3. }  
    public synchronized int lastIndexOf(Object o) {
        return lastIndexOf(o, elementCount-1);
    }

[java]
view plain
copy
print
?

  1. public synchronized int lastIndexOf(Object o, int index) {  
  2.     if (index >= elementCount)  
  3.         throw new IndexOutOfBoundsException(index + ” >= “+ elementCount);  
  4.   
  5.     if (o == null) {  
  6.         for (int i = index; i >= 0; i–)  
  7.             if (elementData[i]==null)  
  8.                 return i;  
  9.     } else {  
  10.         for (int i = index; i >= 0; i–)  
  11.             if (o.equals(elementData[i]))  
  12.                 return i;  
  13.     }  
  14.     return –1;  
  15. }  
    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
?

  1. public synchronized E elementAt(int index) {  
  2.     if (index >= elementCount) {  
  3.         throw new ArrayIndexOutOfBoundsException(index +  ” >= “ + elementCount);  
  4.     }  
  5.   
  6.     return elementData(index);  
  7. }  
    public synchronized E elementAt(int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
        }

        return elementData(index);
    }

[java]
view plain
copy
print
?

  1. E elementData(int index) {  
  2.     return (E) elementData[index];  
  3. }  
    E elementData(int index) {
        return (E) elementData[index];
    }

(13) public synchronized E firstElement() 源码解释: 返回数组第0个位置的元素。
[java]
view plain
copy
print
?

  1. public synchronized E firstElement() {  
  2.     if (elementCount == 0) {  
  3.         throw new NoSuchElementException();  
  4.     }  
  5.     return elementData(0);  
  6. }  
    public synchronized E firstElement() {
        if (elementCount == 0) {
            throw new NoSuchElementException();
        }
        return elementData(0);
    }

(14) public synchronized E lastElement() 源码解释: 返回数组最后一个位置的元素。

[java]
view plain
copy
print
?

  1. public synchronized E lastElement() {  
  2.     if (elementCount == 0) {  
  3.         throw new NoSuchElementException();  
  4.     }  
  5.     return elementData(elementCount – 1);  
  6. }  
    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
?

  1. public synchronized void setElementAt(E obj, int index) {  
  2.     if (index >= elementCount) {  
  3.         throw new ArrayIndexOutOfBoundsException(index +  ” >= “ +  
  4.                                                  elementCount);  
  5.     }  
  6.     elementData[index] = obj;  
  7. }  
    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
?

  1. public synchronized void removeElementAt(int index) {  
  2.     modCount++;  
  3.     if (index >= elementCount) {  
  4.         throw new ArrayIndexOutOfBoundsException(index +  ” >= “ +  
  5.                                                  elementCount);  
  6.     }  
  7.     else if (index < 0) {  
  8.         throw new ArrayIndexOutOfBoundsException(index);  
  9.     }  
  10.     int j = elementCount – index – 1;        // 获取第index位置后有多少个元素  
  11.     if (j > 0) {  
  12.         System.arraycopy(elementData, index + 1, elementData, index, j);     // 将emlementData[j, elementCount]复制到elementData[0, index]的后面  
  13.     }  
  14.     elementCount–;  
  15.     elementData[elementCount] = null// 等待GC  
  16. }  
    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
?

  1. public synchronized void insertElementAt(E obj,  int index) {  
  2.     modCount++;  
  3.     if (index > elementCount) {  
  4.         throw new ArrayIndexOutOfBoundsException(index  
  5.                                                  + ” > “ + elementCount);  
  6.     }  
  7.     ensureCapacityHelper(elementCount + 1);     // 判断是否需要扩容  
  8.     System.arraycopy(elementData, index, elementData, index + 1, elementCount – index); // 将elementData[index+1, elementCount]复制到elementData[index+1, elementCount +1]位置,  
  9.     elementData[index] = obj;   // 在index位置赋值obj  
  10.     elementCount++;  
  11. }  
    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
?

  1. public synchronized void addElement(E obj) {  
  2.     modCount++;  
  3.     ensureCapacityHelper(elementCount + 1);  
  4.     elementData[elementCount++] = obj;  
  5. }  
    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
?

  1. public synchronized boolean removeElement(Object obj) {  
  2.     modCount++;  
  3.     int i = indexOf(obj);  
  4.     if (i >= 0) {  
  5.         removeElementAt(i);  
  6.         return true;  
  7.     }  
  8.     return false;  
  9. }  
    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
?

  1. public synchronized void removeAllElements() {  
  2.     modCount++;  
  3.     // Let gc do its work  
  4.     for (int i = 0; i < elementCount; i++)  
  5.         elementData[i] = null;  
  6.   
  7.     elementCount = 0;  
  8. }  
    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
?

  1. public synchronized E get(int index) {  
  2.     if (index >= elementCount)  
  3.         throw new ArrayIndexOutOfBoundsException(index);  
  4.   
  5.     return elementData(index);  
  6. }  
    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
?

  1. public synchronized E set(int index, E element) {  
  2.     if (index >= elementCount)  
  3.         throw new ArrayIndexOutOfBoundsException(index);  
  4.   
  5.     E oldValue = elementData(index);  
  6.     elementData[index] = element;  
  7.     return oldValue;  
  8. }  
    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
?

  1. public synchronized boolean add(E e) {  
  2.     modCount++;  
  3.     ensureCapacityHelper(elementCount + 1);  
  4.     elementData[elementCount++] = e;  
  5.     return true;  
  6. }  
    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
?

  1. public boolean remove(Object o) {  
  2.     return removeElement(o);  
  3. }  
    public boolean remove(Object o) {
        return removeElement(o);
    }

(25) public void add(int index, E element) 源码解释: 添加元素,和insertElementAt方法一样。

[java]
view plain
copy
print
?

  1. public void add(int index, E element) {  
  2.     insertElementAt(element, index);  
  3. }  
    public void add(int index, E element) {
        insertElementAt(element, index);
    }

(26) public synchronized E remove(int index) 源码解释: 移除index位置的元素。实现思路和removeElementAt类似。

[java]
view plain
copy
print
?

  1. public synchronized E remove(int index) {  
  2.     modCount++;  
  3.     if (index >= elementCount)  
  4.         throw new ArrayIndexOutOfBoundsException(index);  
  5.     E oldValue = elementData(index);    // 获取到旧值  
  6.   
  7.     int numMoved = elementCount – index – 1;     // index位置后面元素的个数  
  8.     if (numMoved > 0)  
  9.         System.arraycopy(elementData, index+1, elementData, index, numMoved);   // 将elementData[index+1, elementCount]移到element[0, index]后  
  10.     elementData[–elementCount] = null// Let gc do its work  
  11.   
  12.     return oldValue;  
  13. }  
    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
?

  1. public void clear() {  
  2.     removeAllElements();  
  3. }  
    public void clear() {
        removeAllElements();
    }

(28) public synchronized boolean containsAll(Collection<?> c) 源码解释: 判断是否包含集合c的所有元素。调用AbstractCollection的实现,代码也很简单,不赘叙。
[java]
view plain
copy
print
?

  1. public synchronized boolean containsAll(Collection<?> c) {  
  2.     return super.containsAll(c);  
  3. }  
    public synchronized boolean containsAll(Collection<?> c) {
        return super.containsAll(c);
    }

[java]
view plain
copy
print
?

  1. public boolean containsAll(Collection<?> c) {  
  2.     for (Object e : c)  
  3.         if (!contains(e))  
  4.             return false;  
  5.     return true;  
  6. }  
    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
?

  1.     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; }  
  2. <pre></pre>  
  3. <br>  
  4. (30public synchronized boolean removeAll(Collection<?> c)  
    public synchronized boolean addAll(Collection<? extends E> c) {
    
     
      
       [java] 
       view plain
        copy 
        print
       ?
      
     
     
  
  1. 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) 源码解释: 将包含集合c的所有元素移除。调用AbstractCollection的实现,代码也很简单,不赘叙。

[java]
view plain
copy
print
?

  1. public boolean removeAll(Collection<?> c) {  
  2.         Objects.requireNonNull(c);  
  3.         boolean modified = false;  
  4.         Iterator<?> it = iterator();  
  5.         while (it.hasNext()) {  
  6.             if (c.contains(it.next())) {  
  7.                 it.remove();  
  8.                 modified = true;  
  9.             }  
  10.         }  
  11.         return modified;  
  12.     }  
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
print
?

  1. public synchronized boolean retainAll(Collection<?> c) {  
  2.      return super.retainAll(c);  
  3.  }  
   public synchronized boolean retainAll(Collection<?> c) {
        return super.retainAll(c);
    }

[java]
view plain
copy
print
?

  1. public boolean retainAll(Collection<?> c) {  
  2.     Objects.requireNonNull(c);  
  3.     boolean modified = false;  
  4.     Iterator<E> it = iterator();  
  5.     while (it.hasNext()) {  
  6.         if (!c.contains(it.next())) {  
  7.             it.remove();  
  8.             modified = true;  
  9.         }  
  10.     }  
  11.     return modified;  
  12. }  
    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
print
?

  1. public synchronized boolean addAll(int index, Collection<?  extends E> c) {  
  2.     modCount++;  
  3.     if (index < 0 || index > elementCount)  
  4.         throw new ArrayIndexOutOfBoundsException(index);  
  5.   
  6.     Object[] a = c.toArray();  
  7.     int numNew = a.length;  
  8.     ensureCapacityHelper(elementCount + numNew);  
  9.   
  10.     int numMoved = elementCount - index;  
  11.     if (numMoved > 0)  
  12.         System.arraycopy(elementData, index, elementData, index + numNew,  
  13.                          numMoved);  
  14.   
  15.     System.arraycopy(a, 0, elementData, index, numNew);  
  16.     elementCount += numNew;  
  17.     return numNew != 0;  
  18. }  
    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
print
?

  1. public synchronized List<E> subList(int fromIndex,  int toIndex) {  
  2.     return Collections.synchronizedList(super.subList(fromIndex, toIndex),  
  3.                                         this);  
  4. }  
    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
print
?

  1. protected synchronized void removeRange(int fromIndex,  int toIndex) {  
  2.      modCount++;  
  3.      int numMoved = elementCount - toIndex;  
  4.      System.arraycopy(elementData, toIndex, elementData, fromIndex,  
  5.                       numMoved);  
  6.   
  7.      // Let gc do its work  
  8.      int newElementCount = elementCount - (toIndex-fromIndex);  
  9.      while (elementCount != newElementCount)  
  10.          elementData[--elementCount] = null;  
  11.  }  
   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
print
?

  1. public synchronized ListIterator<E> listIterator(int index) {  
  2.         if (index < 0 || index > elementCount)  
  3.             throw new IndexOutOfBoundsException( "Index: "+index);  
  4.         return new ListItr(index);  
  5.     }  
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
print
?

  1. public synchronized ListIterator<E> listIterator() {  
  2.     return new ListItr(0);  
  3. }  
    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
print
?

  1. public synchronized Iterator<E> iterator() {  
  2.     return new Itr();  
  3. }  
    public synchronized Iterator<E> iterator() {
        return new Itr();
    }

(38) public Spliterator<E> spliterator() 源码解释: 实例化一个VectorSpliterator对象,并返回。VectorSpliterator是JDK1.8之后LinkedList新增的内部类,因为用得比较少,我就不在这里班门弄斧了,大家有需要可以自行深入研究。

[java]
view plain
copy
print
?

  1. public Spliterator<E> spliterator() {  
  2.     return new VectorSpliterator<>(this null0, -10);  
  3. }  
    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都是围绕这几个方法来进行扩展。

    原文作者:java集合源码分析
    原文地址: https://juejin.im/entry/59eda7e26fb9a0452935ec54
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞