首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Java Stack源码解读和简单应用

说到栈,人们对它再熟悉不过,后进先出说的就是它。

在前面的文章里,我还使用LinkedList、ArrayQueue操作栈的使用。其实呢,在 java.util 包里也有对应的类 Stack,今天一起看下它。

一、Stack简介

Java 中的 Stack 类是一个表示后进先出(LIFO, Last In First Out)栈的类,它继承自 Vector 类,意味着它不仅具有栈的特性(如弹出、推入操作),还继承了 Vector 提供的动态数组特性。尽管 Stack 类在实际开发中不常用(因为 Deque 更常用于实现栈),它仍然是 Java 早期版本中的一部分,提供了一些栈相关的功能。

二、Stack源码解读

Stack 类位于 java.util 包中,继承自 Vector 类。它本质上是对 Vector 的封装,添加了栈相关的操作方法。

public class Stack<E> extends Vector<E> {

public E push(E item); // 推入元素

public synchronized E pop(); // 弹出元素

public synchronized E peek(); // 查看栈顶元素

public boolean empty(); // 判断栈是否为空

public synchronized int search(Object o); // 查找元素在栈中的位置

}

1. 构造函数

Stack 继承了 Vector 的构造函数,所以可以通过不同的构造方式创建一个 Stack 对象。例如:

Stack<Integer> stack = new Stack<>(); // 默认构造函数,初始容量是 10

默认情况下,Stack 使用 Vector 的默认容量(10),并且可以自动增长。

2. 推入元素 (push)

push() 方法将一个元素压入栈顶。

它实际上是调用 Vector 类的 addElement() 方法向 Vector 追加一个元素。Vector 类的 addElement() 方法通过 grow() 来确保有足够的空间容纳新元素。

public E push(E item) {

addElement(item); // 向 Vector 追加元素

return item;

}

push() 方法是线程安全的,因为它是同步的。它将元素推入栈顶并返回该元素。

3. 弹出元素 (pop)

pop() 方法将栈顶元素弹出并返回。

它会先调用 peek() 方法查看栈顶元素,然后使用 removeElementAt() 从 Vector 中删除该元素。pop() 方法是同步的。

public synchronized E pop() {

if (empty()) {

throw new EmptyStackException(); // 如果栈为空,则抛出异常

}

E obj = peek();

removeElementAt(size() - 1); // 删除栈顶元素

return obj;

}

pop() 方法首先检查栈是否为空,如果为空,则抛出 EmptyStackException 异常。

然后它返回栈顶元素,并删除该元素。

4. 查看栈顶元素 (peek)

peek() 方法返回栈顶的元素,但不删除它。如果栈为空,它会抛出 EmptyStackException 异常。

public synchronized E peek() {

if (empty()) {

throw new EmptyStackException(); // 如果栈为空,则抛出异常

}

return elementAt(size() - 1); // 返回栈顶元素

}

peek() 方法通过 elementAt(size() - 1) 获取栈顶元素。size() 返回当前栈的元素数量,elementAt() 获取指定索引的元素。

5. 判断栈是否为空 (empty)

empty() 方法检查栈是否为空。如果栈为空,则返回 true,否则返回 false。

public boolean empty() {

return size() == 0; // 如果栈中没有元素,返回 true

}

empty() 方法通过检查栈的大小来确定栈是否为空,返回值是一个布尔值。

6. 查找元素的位置 (search)

search() 方法用于查找元素在栈中的位置。它返回元素与栈顶的相对位置。如果元素不存在,返回 -1。

public synchronized int search(Object o) {

int i = lastIndexOf(o); // 在栈中从顶部查找该元素

if (i >= 0) {

return size() - i; // 返回相对于栈顶的索引

}

return -1; // 如果没有找到元素,返回 -1

}

search() 方法通过 lastIndexOf() 来查找元素在栈中的位置,并返回相对于栈顶的索引。如果栈中没有该元素,返回 -1。

Stack 类的所有方法都是同步的,这意味着它是线程安全的。在多个线程访问 Stack 时,操作是按顺序执行的,避免了数据的不一致。然而,由于线程同步的开销,Stack 在性能上不如 Deque(例如 ArrayDeque)等更现代的数据结构。

三、应用示例

public class StackExample {

public static void main(String[] args) {

Stack<Integer> stack = new Stack<>();

// 推入元素

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.peek()); // 输出 2

// 判断栈是否为空

System.out.println("栈是否为空: " + stack.empty()); // 输出 false

// 查找元素位置

System.out.println("元素 2 的位置: " + stack.search(2)); // 输出 1

}

}

四、最后总结

Stack 类继承自 Vector,并通过同步操作提供线程安全的栈功能。

栈的基本操作包括推入元素(push())、弹出元素(pop())、查看栈顶元素(peek())以及判断栈是否为空(empty())。Stack 类中的 search() 方法可以查找栈中某个元素的相对位置。

由于性能问题,Stack 类在现代 Java 开发中并不常用,通常使用 Deque(如 ArrayDeque)来实现栈的功能。Stack 是一个慢慢被遗忘的类,但它真实存在。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OiqspgAU2HRymiuCtROTQ-cA0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券