JAVA 集合类(java.util)源码阅读笔记------Vector

Posted Itzel_yuki

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA 集合类(java.util)源码阅读笔记------Vector相关的知识,希望对你有一定的参考价值。

一、继承关系

public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
(1)继承自AbstractList类
(2)List接口:继承自Collection接口,同时自己也定义了一系列索引访问功能。
(3)RandomAccess:空接口,实现该接口代表该类拥有随机访问list对象的能力。
(4)Cloneable:空接口,实现该接口,重写Object的clone方法,否则会抛出异常。调用super.clone()实现对象的复制,如果对象中有引用,可以在super.clone后面进行处理。
(5)java.io.Serializable:空接口,实现该接口代表该类可序列化


二、成员变量

protected Object[] elementData;//内部还是采用一个数组保存list中的元素
protected int elementCount;//数组实际包含的元素的个数
protected int capacityIncrement;//每次增长的大小(不是增长率),当值小于等于0时,容量每次增长的容量为elementData.length(即倍增原数组的大小)
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //数组的最大容量

三、方法说明

(1)构造方法,如果不提供初始容量,则默认数组大小为10

	public Vector() 
        this(10);
    


(2)同步方法:trimToSize,将数组的容量修改成实际容量的大小,即令elementData.length=elementCount

    public synchronized void trimToSize() 
        modCount++;
        int oldCapacity = elementData.length;
        if (elementCount < oldCapacity) 
            elementData = Arrays.copyOf(elementData, elementCount);
        
    


(3)同步方法:ensureCapacity,保证数组的最小容量

    public synchronized void ensureCapacity(int minCapacity) 
        if (minCapacity > 0) 
            modCount++;
            ensureCapacityHelper(minCapacity);
        
    
	//调用了ensureCapacityHelper:
    private void ensureCapacityHelper(int minCapacity) 
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    
	//调用了grow:
    private void grow(int minCapacity) 
        // overflow-conscious code
        int oldCapacity = elementData.length;
		//如果capacityIncrement<0,则newCapacity=oldCapacity+oldCapacity;
		//否则则newCapacity=oldCapacity+capacityIncrement;
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
		//如果增长后仍不能保证满足minCapacity,则令newCapacity = minCapacity
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
		//若增长后的大小大于允许的最大长度,则调用hugeCapacity
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
		//调用Arrays.copyof方法将elementData拷贝到一个容量为newCapacity的数组中。
		//Arrays.copyOf(elementData, newCapacity)实际上是通过System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));来实现的
        elementData = Arrays.copyOf(elementData, newCapacity);
    
	//调用了hugeCapacity
    private static int hugeCapacity(int minCapacity) 
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
		//MAX_ARRAY_SIZE=Integer.MAX_VALUE-8
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    


(4)同步方法:setSize,将elementData.length设置为newSize

    public synchronized void setSize(int newSize) 
        modCount++;
        if (newSize > elementCount) 
		//若newSize<elementData.length,则不用扩容,否则需要扩容
            ensureCapacityHelper(newSize);
         else 
		//若newSize<elementData的实际大小(elementCount),则将newSize及其后面的数组都置为空
            for (int i = newSize ; i < elementCount ; i++) 
                elementData[i] = null;
            
        
        elementCount = newSize;
    


(5)同步方法:capacity,返回数组的大小;size,返回数组包含的元素的个数;isEmpty,判断数组是否没有元素

    public synchronized int capacity() 
        return elementData.length;
    
	public synchronized int size() 
        return elementCount;
    
	public synchronized boolean isEmpty() 
        return elementCount == 0;
    


(6)同步方法:删除index处的元素

    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;
        if (j > 0) 
		//将elementData从index+1到elementCount为止的元素向前移动一个位置,覆盖Index处的元素
            System.arraycopy(elementData, index + 1, elementData, index, j);
        
        elementCount--;
        elementData[elementCount] = null; /* to let gc do its work */
    
	//remove也是删除,但是没有判断index是否小于0
	public synchronized E remove(int index) 
        modCount++;
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);
        E oldValue = elementData(index);

        int numMoved = elementCount - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--elementCount] = null; // Let gc do its work

        return oldValue;
    


(7)同步方法:insertElementAt,在index处插入obj。

    public synchronized void insertElementAt(E obj, int index) 
        modCount++;
        if (index > elementCount) 
            throw new ArrayIndexOutOfBoundsException(index
                                                     + " > " + elementCount);
        
		//先保证容量大于elementCount+1
        ensureCapacityHelper(elementCount + 1);
		//将elementData数组中index到elementCount之间的元素向后移动一位,给Index处空出位置
        System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
        elementData[index] = obj;
        elementCount++;
    


(8)同步方法:clone,重写Object父类中的方法

    public synchronized Object clone() 
        try 
            @SuppressWarnings("unchecked")
                Vector<E> v = (Vector<E>) super.clone();
			//复制一个Vector对象,然后给该对象中的elementData分配空间和填充元素
            v.elementData = Arrays.copyOf(elementData, elementCount);
            v.modCount = 0;
            return v;
         catch (CloneNotSupportedException e) 
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        
    


(9)同步方法:toArray

@SuppressWarnings("unchecked")
    public synchronized <T> T[] toArray(T[] a) 
	//如果参数a的size不够,则重新申请一个数组空间,并且复制elementData中内容
        if (a.length < elementCount)
            return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());

        System.arraycopy(elementData, 0, a, 0, elementCount);

        if (a.length > elementCount)
            a[elementCount] = null;

        return a;
    



四、内部类

(1)Itr:单向迭代器,线程安全
    private class Itr implements Iterator<E> 
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        public boolean hasNext() 
            // Racy but within spec, since modifications are checked
            // within or after synchronization in next/previous
            return cursor != elementCount;
        

        public E next() 
		//加锁,本对象的对象锁
            synchronized (Vector.this) 
                checkForComodification();
                int i = cursor;
                if (i >= elementCount)
                    throw new NoSuchElementException();
                cursor = i + 1;
                return elementData(lastRet = i);
            
        

        public void remove() 
            if (lastRet == -1)
                throw new IllegalStateException();
			//加锁
            synchronized (Vector.this) 
                checkForComodification();
                Vector.this.remove(lastRet);
                expectedModCount = modCount;
            
            cursor = lastRet;
            lastRet = -1;
        

        @Override
        public void forEachRemaining(Consumer<? super E> action) 
            Objects.requireNonNull(action);
			//加锁
            synchronized (Vector.this) 
                final int size = elementCount;
                int i = cursor;
                if (i >= size) 
                    return;
                
        @SuppressWarnings("unchecked")
                final E[] elementData = (E[]) Vector.this.elementData;
                if (i >= elementData.length) 
                    throw new ConcurrentModificationException();
                
                while (i != size && modCount == expectedModCount) 
                    action.accept(elementData[i++]);
                
                // update once at end of iteration to reduce heap write traffic
                cursor = i;
                lastRet = i - 1;
                checkForComodification();
            
        

        final void checkForComodification() 
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        
    


(2)双向迭代器:ListItr,线程安全
    final class ListItr extends Itr implements ListIterator<E> 
         ListItr(int index) 
            super();
            cursor = index;
        

        public boolean hasPrevious() 
            return cursor != 0;
        

        public int nextIndex() 
            return cursor;
        

        public int previousIndex() 
            return cursor - 1;
        

        public E previous() 
		//加锁
            synchronized (Vector.this) 
                checkForComodification();
                int i = cursor - 1;
                if (i < 0)
                    throw new NoSuchElementException();
                cursor = i;
                return elementData(lastRet = i);
            
        

        public void set(E e) 
            if (lastRet == -1)
                throw new IllegalStateException();
			//加锁
            synchronized (Vector.this) 
                checkForComodification();
                Vector.this.set(lastRet, e);
            
        

        public void add(E e) 
            int i = cursor;
			//加锁
            synchronized (Vector.this) 
                checkForComodification();
                Vector.this.add(i, e);
                expectedModCount = modCount;
            
            cursor = i + 1;
            lastRet = -1;
        
    


(3)并行迭代器
static final class VectorSpliterator<E> implements Spliterator<E>

五、Iterator和Enumeration比较

在Java集合中,我们通常都通过 “Iterator(迭代器)” 或 “Enumeration(枚举类)” 去遍历集合。今天,我们就一起学习一下它们之间到底有什么区别。
我们先看看 Enumeration.java 和 Iterator.java的源码,再说它们的区别。
Enumeration是一个接口,它的源码如下:
package java.util;

public interface Enumeration<E> 

    boolean hasMoreElements();

    E nextElement();
Iterator也是一个接口,它的源码如下:
package java.util;

public interface Iterator<E> 
    boolean hasNext();

    E next();

    void remove();
看完代码了,我们再来说说它们之间的区别。
(01) 函数接口不同
        Enumeration只有2个函数接口。通过Enumeration,我们只能读取集合的数据,而不能对数据进行修改。
        Iterator只有3个函数接口。Iterator除了能读取集合的数据之外,也能数据进行删除操作。
(02) Iterator支持fail-fast机制,而Enumeration不支持。
        Enumeration 是JDK 1.0添加的接口。使用到它的函数包括Vector、Hashtable等类,这些类都是JDK 1.0中加入的,Enumeration存在的目的就是为它们提供遍历接口。Enumeration本身并没有支持同步,而在Vector、Hashtable实现Enumeration时,添加了同步。
        而Iterator 是JDK 1.2才添加的接口,它也是为了HashMap、ArrayList等集合提供遍历接口。Iterator是支持fail-fast机制的:当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。
Enumeration速度比Iterator快。







以上是关于JAVA 集合类(java.util)源码阅读笔记------Vector的主要内容,如果未能解决你的问题,请参考以下文章

JAVA 集合类(java.util)源码阅读笔记------ArrayList

JAVA 集合类(java.util)源码阅读笔记------Hashtable

JAVA 集合类(java.util)源码阅读笔记------HashMap

JAVA 集合类(java.util)源码阅读笔记------WeakHashMap

JAVA 集合类(java.util)源码阅读笔记------Stack

源码阅读(30):Java中线程安全的QueueDeque结构——概述