【源码】Vector、Stack源码解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/RowandJJ/article/details/38494183

注:以下源码基于jdk1.7.0_11


Vector算是一个历史遗留下来的类,现在已基本被ArrayList取代。本文出于学习的目的来分析下这个类。

从图上可以看出Vector和ArrayList同样都直接继承于AbstractList,说明这两者功能上还是很相像的,事实也正是如此。
下面我们依然通过源码的方式解读Vector这个类。
public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
Vector的继承关系和ArrayList保持一致。但是成员变量确不太一样:

  protected Object[] elementData;//使用数组存储元素
  protected int elementCount;//元素个数
  protected int capacityIncrement;//扩容增量
   /** use serialVersionUID from JDK 1.0.2 for interoperability */
  private static final long serialVersionUID = -2767605614048989439L;

Vector多了一个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;
    }

    public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }

    public Vector() {//默认大小为10
        this(10);
    }
    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);
    }

除此之外,Vector的初始容量与ArrayList一样,都是10。
下面来看下Vector的扩容机制
public synchronized void ensureCapacity(int minCapacity) {
        if (minCapacity > 0) {
            modCount++;
            ensureCapacityHelper(minCapacity);
        }
    }
    private void ensureCapacityHelper(int minCapacity) {
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    private void grow(int minCapacity) {//扩容的方法
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

但从方法命名上来看,跟ArrayList还是很类似的,但是两者的grow方法有点小区别:
Vector的扩容是基于capacityIncrement的,也就是所谓的扩容增量,如果该值不为0,那么每次扩容后的大小就是在原始容量加上扩容增量。如果未设置capacityIncrement,那么直接扩容为原来的两倍。
当然,前提是扩容后大小得大于等于所需要的最小容量minCapacity且不能超过MAX_ARRAY_SIZE,同时还要防止溢出(会抛出异常)。顺便复习下ArrayList的扩容机制:ArrayList每次扩容后大小都为原来的1.5倍
接下来,我们观察一些方法:
 public synchronized void trimToSize() {
        modCount++;
        int oldCapacity = elementData.length;
        if (elementCount < oldCapacity) {
            elementData = Arrays.copyOf(elementData, elementCount);
        }
    }
   public synchronized int size() {
        return elementCount;
    }
 public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }
   public synchronized boolean removeElement(Object obj) {
        modCount++;
        int i = indexOf(obj);
        if (i >= 0) {
            removeElementAt(i);
            return true;
        }
        return false;
    }

可以发现,这些方法都加上了synchronized关键字,也就是说Vector是一个线程安全的类
另外,Vector也是支持null元素的。
 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;
    }
Vector除了ListIterator和iterator两种迭代方式之外,还有独特的迭代方式,那就是elements方法
  public Enumeration<E> elements() {
        return new Enumeration<E>() {//匿名内部类方式构造一个Enumeration对象。
            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");
            }
        };
    }

这个方法通过匿名内部类的方式构造一个Enumeration对象,并实现了hasMoreElements和nextElement方法,类似迭代器的hasNext和next方法。

以上就是Vector的内容,下面再看看Stack类:
public class Stack<E> extends Vector<E> {

    public Stack() {
    }

    public E push(E item) {//入栈
        addElement(item);
        return item;
    }

    public synchronized E pop() {//出栈
        E       obj;
        int     len = size();
        obj = peek();
        removeElementAt(len - 1);
        return obj;
    }
    public synchronized E peek() {//获取栈顶元素
        int     len = size();
        if (len == 0)
            throw new EmptyStackException();
        return elementAt(len - 1);
    }
    public boolean empty() {//判断栈是否为空
        return size() == 0;
    }

    public synchronized int search(Object o) {
        int i = lastIndexOf(o);
        if (i >= 0) {
            return size() - i;
        }
        return -1;
    }
    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = 1224463164541339165L;
}

总结:
1.Vector是线程安全的类而ArrayList不是;
2.Vector的扩容基于扩容增量,若扩容增量不为0,每次扩容的大小都为原始容量加上扩容增量,若扩容增量为0,也就是默认的情况下,扩容大小为元素容量的两倍;
3.Vector默认大小为10;
4.Vector支持null(ArrayList也可以);
5.Vector除了可以使用listIterator和Iterator遍历集合,也可以使用Enumeration的方式遍历;
6.Stack类继承了Vector,并封装了栈的操作。同时也是一个线程安全的类。
7.从性能上看,推荐使用ArrayList和LinkedList而不要使用Vector和Stack。






展开阅读全文

没有更多推荐了,返回首页