Stack
2022-02-25 本文已影响0人
Alsan_L3
Stack,中文名:栈,这个词在开发过程中经常会提到,但是,实际开发中用到Stack这个类就很少了,我们用的最多的还是ArrayList和HashMap。
那么,我们什么情况下会用到这个类呢,我们来看看这个类是如何实现的,Stack的源码很短,大家可以很快就看完,我们先来看下类的声明:
public class Stack<E> extends Vector<E> {}
这里可以看到Stack继承自Vector,那么Vector又是什么呢,我们继续看:
public class Vector<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{}
是不是看着有点眼熟,对的,我们之前分析过ArrayList的实现,ArrayList跟Vector继承和实现的接口是一样的,所以说Vector(Stack)也是一个List,拥有List的一切特性。
另外,Stack栈我们都知道他的定义:先进后出。那么他是怎么实现先进后出的呢,接下来我们来看Stack的几个方法:
boolean empty() //测试栈是否为空
Object peek( )//查看栈顶部的对象,但不从栈中移除它
Object pop( )//移除栈顶部的对象,并作为此函数的值返回该对象
Object push(Object element)//把项压入栈顶部
int search(Object element)//返回对象在栈中的位置,以 1 为基数
关注pop和push两个方法,实现了栈的先进后出,我们来看push的实现:
public E push(E item) {
addElement(item);
return item;
}
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
可以看出里面的实现也是基于数组完成的,与add调用的是同一个方法,都是在数组后面增加一个元素;接着我们来看pop方法:
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
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) {
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}
首先通过peek拿到栈顶元素,然后调用removeElementAt(len-1)方法去移除最后一个元素,移除操作也是通过数组拷贝实现的。
前面我们知道,Stack实现了List的所有特性,并且里面都是通过数组实现的,除了上面拥有栈先进后出的特性外,它与ArrayList还有什么区别呢,我们可以从源码中方法声明可以看到,Vector和Stack的方法都带了synchronized关键字,说明Stack是线程安全的。之前我们分析过ArrayList,它不是线程安全的,所以以后如果有需求要用到线程安全的List或者要实现先进后出的特性,都可以用Stack这个类。
好了,今天内容就到这里了,明天继续。