Java中的堆栈(Stack)技术详解

73 阅读2分钟

在Java编程中,堆栈(Stack)是一种重要的数据结构,它遵循后进先出(LIFO,Last In First Out)的原则,即最后一个入栈的元素总是第一个出栈。Java标准库并没有直接提供一个名为“Stack”的类,但我们可以使用java.util.Stack类或者更常用的java.util.Deque接口(如ArrayDequeLinkedList)来实现堆栈的功能。由于java.util.Stack类被认为是遗留类,因此在现代编程中更推荐使用Deque接口的实现类。

Stack的基本操作

  1. push(E item) :将元素压入栈顶。
  2. pop() :移除栈顶元素并返回该元素。如果此堆栈为空,则抛出NoSuchElementException
  3. peek() :检索但不移除此堆栈的顶部元素。如果此堆栈为空,则抛出NoSuchElementException
  4. empty() :测试此堆栈是否为空。
  5. search(Object o) :返回对象在此堆栈中的从1开始的偏移量;如果此堆栈不包含该对象,则返回-1。

使用Deque接口实现Stack

由于Deque接口提供了双端队列的功能,我们可以使用其pushpop, 和 peek等方法来实现堆栈的功能。以下是一个使用ArrayDeque实现堆栈的示例:

java复制代码
	import java.util.ArrayDeque;  

	import java.util.Deque;  

	  

	public class StackExample {  

	    private Deque<Integer> stack;  

	  

	    public StackExample() {  

	        stack = new ArrayDeque<>();  

	    }  

	  

	    public void push(int item) {  

	        stack.push(item);  

	    }  

	  

	    public int pop() {  

	        if (!stack.isEmpty()) {  

	            return stack.pop();  

	        } else {  

	            throw new EmptyStackException();  

	        }  

	    }  

	  

	    public int peek() {  

	        if (!stack.isEmpty()) {  

	            return stack.peek();  

	        } else {  

	            throw new EmptyStackException();  

	        }  

	    }  

	  

	    public boolean isEmpty() {  

	        return stack.isEmpty();  

	    }  

	  

	    public static void main(String[] args) {  

	        StackExample stack = new StackExample();  

	  

	        stack.push(1);  

	        stack.push(2);  

	        stack.push(3);  

	  

	        System.out.println(stack.peek()); // 输出 3  

	  

	        System.out.println(stack.pop()); // 输出 3  

	        System.out.println(stack.pop()); // 输出 2  

	  

	        System.out.println(stack.isEmpty()); // 输出 false  

	    }  

	}

注意事项

  1. 异常处理:当调用poppeek方法时,如果堆栈为空,应该抛出EmptyStackException异常。
  2. 线程安全ArrayDequeLinkedList等非线程安全的类在多线程环境中使用时需要额外的同步措施。如果需要线程安全的堆栈,可以使用java.util.concurrent.ConcurrentLinkedQueuejava.util.concurrent.Stack(尽管java.util.concurrent.Stack通常不被推荐,因为它扩展了遗留的Vector类)。
  3. 性能:堆栈操作(如push和pop)在数组实现和链表实现中通常具有常数时间复杂度(O(1))。但是,如果底层数据结构(如ArrayList)在push操作时需要重新分配内存,则性能可能会受到影响。
  4. 应用场景:堆栈在许多场景中都非常有用,例如函数调用栈、浏览器的前进后退功能、撤销操作等。