1.Stack的基本介绍
Stack是一种后进先出(LIFO)的结构,其继承了Vector的基础上拓展5个方法push()、pop()、peek()、empty()、search()而来
a、push(E):将item推入到栈中,依次加入数组中(数组尾部)。
b、pop() :将栈中的最顶一个(数组尾部)item推出,并返回被推出的item
e、peek():返回栈中最顶(数组尾部)的一个item,但不对其做任何操作
d、empty():判断该栈是否为空
e、search(Object):搜索某一个item在该栈中的位置【位置为离栈顶最近的item与栈顶间距离】
PS:虽然Java有提供该类型的数据结构,但是官方推荐使用Deque【双端队列】,Deque提供更好的完整性和一致性,应该优先使用。
Stack基于Vector(Vector的方法用Synchronized修饰的),另外Stack中的pop、peek、search方法夜都是用Synchronized修饰的,所以Stack是线程安全的。
2.Stack的类结构
public class Stack<E> extends Vector<E> {
......
}
3.Stack的成员变量
Stack本身类中没有成员变量,但是因为Stack继承了Vector类,所以咱们得看下Vector的成员变量。
//存储数据的数组
protected Object[] elementData;
//实际存储的元素个数
protected int elementCount;
//扩容的增量值
protected int capacityIncrement;
4.Stack的构造函数
Stack只有一个构造函数。
public Stack() {}
由于Stack继承了Vector,所以咱们还得看下Vector的构造函数
public Vector() {
//默认初始大小是10
this(10);
}
public Vector(int initialCapacity) {
//默认增量为0
this(initialCapacity, 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;
}
5.Stack的主要方法
5.1添加
public E push(T item);
public E push(E item) {
//添加元素
addElement(item);
//返回添加的元素
return item;
}
//该方法是Vector的方法
//该方法使用synchronized修饰了,所以是线程安全的
public synchronized void addElement(E obj) {
//修改次数加一
modCount++;
//判断是否需要扩容
ensureCapacityHelper(elementCount + 1);
//将被添加的对象放置在elementCount++位置,即size+1
elementData[elementCount++] = obj;
}
//该方法是Vector的方法
private void ensureCapacityHelper(int minCapacity) {
//判断是否需要扩容:size+1是否大于当前数组的长度
if (minCapacity - elementData.length > 0)
//扩容
grow(minCapacity);
}
//该方法是Vector的方法
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//capacityIncrement为每次扩容的增量
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);
}
通过查看源码我们发现Stack的底层数据结构也是数组,可以动态扩容,和ArrayList的底层数据结构是一样的,但是扩容方法有区别,ArrayList一般是扩容至1.5倍,而Stack有个扩容增量值,如果该增量值大于零,新容量值就等于就容量值加上增量值,否则即为旧容量值的两倍。
5.2.public synchronized E peek();返回栈顶(数组尾部)的元素,但不将其从栈中删除。
public synchronized E peek() {
//获取当前数组中元素个数
int len = size();
if (len == 0)
throw new EmptyStackException();
//返回数组尾部元素,所以后进先出
return elementAt(len - 1);
}
//Vector中的方法
public synchronized E elementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
}
return elementData(index);
}
//Vector中的方法
E elementData(int index) {
return (E) elementData[index];
}
5.3.public synchronized E pop():返回栈顶(数组尾部)的元素,并将其从栈中删除。
public synchronized E pop() {
E obj;
int len = size();
//获取数组尾部元素
obj = peek();
//将尾部元素删除
removeElementAt(len - 1);
return obj;
}
5.4.public synchronized int search(Object o);
public synchronized int search(Object o) {
//返回数组中最后一个元素为o的下角标
int i = lastIndexOf(o);
if (i >= 0) {
//返回栈顶(数组尾部)与该元素的距离
return size() - i;
}
return -1;
}
至此,java.util.Stack的基本介绍完成!。