首页 > 学院 > 开发设计 > 正文

Vector与Stack源码分析

2019-11-11 04:15:32
字体:
来源:转载
供稿:网友

Vector类从JDk 1.0开始就存在了,其类的继承关系如下: Vector继承关系图 从上图可以发现Vector的继承关系与ArrayList的继承关系相同,功能上Vector与ArrayList也是一样的,都是一个扩展的列表。区别在于Vector是线程安全的,而ArrayList不是线程安全的。 Stack类代表的是一个LIFO的栈,该类的继承关系如下: Stack继承关系图 可以看到Stack继承自Vector类,在Vector的基础上提供了5个操作使Vector具备Stack的性质。五个方法分别是push、pop、peek、检测栈是否为空基于一个搜索方法。 下面先介绍Vector的源码,最后介绍一下Stack。

Vector源码介绍

构造器

Vector有四个构造方法,其内部有两个重要的参数,一个是elementCount代表当前元素个数,一个是capacityIncrement,代表当列表元素满了之后增加的容量。如果不设置capacityIncrement,那么Vector容量扩展时默认将扩展两倍,在ArrayList源码分析中,我们知道ArrayList在扩容时默认将扩展1.5倍,所以这又是ArrayList与Vector的一个区别。

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() { 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初始时容量为10,而ArrayList初始容量为0。

添加操作

下面就以add(E e)方法为例介绍一个,其余方法与ArrayList中的流程类似。add()方法的实现如下:

public synchronized boolean add(E e) { modCount++; //确保容量足够 ensureCapacityHelper(elementCount + 1); //添加元素 elementData[elementCount++] = e; return true; }

从上面代码可以看到,add()方法用synchronized关键字修饰,所以是线程安全的,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; 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); }

可以看到,如果capacityIncrement为0时,那么newCapacity将会是两倍的oldCapacity,后面的操作与ArrayList中的相同。下面看一下ArrayList的grow方法可以看到区别。

private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); }

从上面就可以看出两个类在得到newCapacity变量时的区别。 其他add方法与ArrayList相同,只不过每个方法多了synchronized关键字修饰。

其余操作

其余操作与ArrayList类似,只不过每个方法都多了synchronized关键字,从而保证了Vector类的线程安全。

Stack源码分析

Stack类的实现比较简单,只是在Vector的基础上添加了一个方法,下面是Stack类的实现:

publicclass Stack<E> extends Vector<E> { /** * Creates an empty Stack. */ public Stack() { } /** * Pushes an item onto the top of this stack. This has exactly * the same effect as: * <blockquote><pre> * addElement(item)</pre></blockquote> * * @param item the item to be pushed onto this stack. * @return the <code>item</code> argument. * @see java.util.Vector#addElement */ public E push(E item) { addElement(item); return item; } /** * Removes the object at the top of this stack and returns that * object as the value of this function. * * @return The object at the top of this stack (the last item * of the <tt>Vector</tt> object). * @throws EmptyStackException if this stack is empty. */ public synchronized E pop() { E obj; int len = size(); obj = peek(); removeElementAt(len - 1); return obj; } /** * Looks at the object at the top of this stack without removing it * from the stack. * * @return the object at the top of this stack (the last item * of the <tt>Vector</tt> object). * @throws EmptyStackException if this stack is empty. */ public synchronized E peek() { int len = size(); if (len == 0) throw new EmptyStackException(); return elementAt(len - 1); } /** * Tests if this stack is empty. * * @return <code>true</code> if and only if this stack contains * no items; <code>false</code> otherwise. */ public boolean empty() { return size() == 0; } /** * Returns the 1-based position where an object is on this stack. * If the object <tt>o</tt> occurs as an item in this stack, this * method returns the distance from the top of the stack of the * occurrence nearest the top of the stack; the topmost item on the * stack is considered to be at distance <tt>1</tt>. The <tt>equals</tt> * method is used to compare <tt>o</tt> to the * items in this stack. * * @param o the desired object. * @return the 1-based position from the top of the stack where * the object is located; the return value <code>-1</code> * indicates that the object is not on the stack. */ 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;}

从上面的代码可以看到,Stack内部一共五个方法,其中三个方法都加了synchronized关键字,是线程安全的,而push和empty方法调用了Vector的方法,由于Vector中的addElement()和size()方法都是线程安全的,所以Stack的每个方法也都是线程安全的,所以它和Vector一样,都是线程安全的。

总结

Vector与ArrayList的最大区别就是Vector是线程安全的,而ArrayList不是线程安全的。另外区别还有: - ArrayList不可以设置扩展的容量,默认1.5倍;Vector可以设置扩展的容量,如果没有设置,默认2倍 - ArrayList的无参构造方法中初始容量为0,而Vector的无参构造方法中初始容量为10。 - Vector线程安全,ArrayList线程不安全。

Vector和它的子类Stack都是线程安全的集合。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表