栈是先进后出的结构,JDK中提供的Stack类实现基于List,并使用FILO的方法管理数据。
Stack继承自Vector,本质是一个实现了Collection和List接口的类。Vector是一个古老的java类,在JDK1.0上已经开始支持,它是后来者ArrayList的同源兄弟,在看Stack源码前,先从Vector和ArrayList开始。
Vector和ArrayList的关系和对比
而Vector与ArrayList可谓是兄弟,因为它们的继承关系和实现的接口都是一致的,内部数据同样是通过数组来存储。
public class Vector<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
它们之间最大的不同点有2个:
1. Vector操作数组的方法都是同步的(synchronized),而ArrayList是非线程安全的,效率会比Vector高。
2. Vector在扩容时,数组大小会基于现有的长度成倍增加,而ArrayList只会增加现有长度的50%。
Vector操作数据的方法是同步的
Vector和ArrayList各自的插入方法实现基本是一模一样的,区别还真是只有Vector的方法时synchronized的。
//Vector的插入方法
public synchronized void insertElementAt(E obj, int index) {
...
ensureCapacityHelper(elementCount + 1);
System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
elementData[index] = obj;
elementCount++;
}
//ArrayList的插入方法
public void add(int index, E element) {
...
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
Vector与ArrayList扩容方法的对比
//Vector每次扩容后数组长度都会增加一倍
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);
}
//ArrayList长度只会增加当前大小的一半
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); //1.5倍
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);
}
Stack类分析
Stack类实现比较简单,方法实现都是基于Vector类已实现的基本操作(插入/删除/访问/修改等),主要时出栈的逻辑以先进后出的逻辑实现。
进栈
将数据放到栈顶,即数组的最后一个元素。
public E push(E item) {
addElement(item);
return item;
}
//Vector.java
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
出栈
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);
}
搜索
搜索方法调用的是Vector中提供的查找方法,从数组尾部开始查找,及返回离栈顶最近的数据位置。
public synchronized int search(Object o) {
int i = lastIndexOf(o);
if (i >= 0) {
return size() - i;
}
return -1;
}
//Vector.java
public synchronized int lastIndexOf(Object o, int index) {
...
if (o == null) {
...
} else {
for (int i = index; i >= 0; i--) //从数组尾部开始查找
if (o.equals(elementData[i]))
return i;
}
return -1;
}