Java的栈,算是我们在Java中常见的一种数据结构,他遵循先进后出的原则(Last-In-First-Out,LIFO)的原则,在Java中,Stack是通过继承自Vector类实现的。
如上图所示,我们的stack继承自Vector。
我们来看一个简单的案例,实现一个简单的先进后出demo:
public static void main(String[] args) {
// 创建一个Stack对象
Stack<String> stack = new Stack<>();
// 入栈操作
stack.push("Java");
stack.push("Python");
stack.push("C++");
// 出栈操作
while (!stack.isEmpty()) {
String element = stack.pop();
System.out.println("出栈元素: " + element);
}
}
由于Stack继承自Vector,故而Stack中并没有许多新的方法,一般主要操作栈就是在Stack中进栈和出栈,当然还可以判断栈是否为空,以及在栈中搜索相关元素。这个栈里边很多方法来自Vector,直接使用就行,值得注意的是,在Stack中,Java通过五个操作对Vector进行相关拓展,他允许将向量视为堆栈。Stack是Vector的增强类,堆栈顶部对应向量末尾。
boolean empty():测试堆栈是否为空。
public boolean empty() {
return size() == 0;
}
peek() :查看堆栈顶部的对象,但不从堆栈中移除它。
public synchronized E peek() {
//获取向量容量大小
int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);//调用父类Vector的elementAt方法
}
注意堆栈顶部的对象的对象索引对应的是向量末尾。
E pop(): 移除堆栈顶部的对象,并作为此函数的值返回该对象。
public synchronized E pop() {
E obj;
//获取向量大小
int len = size();
//获取堆栈顶部的对象
obj = peek();
//调用父类Vector的removeElementAt方法,移除末尾元素
removeElementAt(len - 1);
return obj;
}
E push(E item):把项压入堆栈顶部。
public E push(E item) {
//调用父类Vector的addElement方法,添加元素至向量末尾
addElement(item);
return item;
}
int search(Object o):返回对象在堆栈中的位置,以 1 为基数。
public synchronized int search(Object o) {
//调用父类Vector的lastIndexOf方法
//返回此向量中最后一次出现的指定元素的索引,从末尾向前搜索,如果未找到该元素,则返回 -1。
int i = lastIndexOf(o);
if (i >= 0) {
return size() - i;
}
return -1;
}
fail-fast(快速失败机制)就是在做系统设计的时候先考虑异常情况,一旦发生异常,直接停止并上报。
由于ArrayList是数组存储形式,在随机查询方面会比较快。若每次add或remove时均在末尾,ArrayList会比较快,直接通过index操作。但若随机add或remove,LinkedList链式存储,相比ArrayList少了System.arrayCopy操作,会快一点,且ArrayList每次随机添加和删除都需要移动元素,故而也会影响相关性能。Vector每个方法都加上synchronized,保证了同步同时,牺牲了性能。