JAVA中栈的使用

栈(Stack)是遵循后进先出(LIFO, Last In First Out) 规则的线性数据结构,Java中有两种主流的栈实现方式:

  1. 遗留类:java.util.Stack(继承自Vector,线程安全但效率低,不推荐使用);
  2. 推荐方式:java.util.Deque(双端队列)接口的实现类(如LinkedList、ArrayDeque),功能更完善、效率更高,是官方推荐的栈替代方案。

一、栈的核心操作(按常用程度排序)

以下先统一说明核心操作的含义,再分别给出Stack和Deque的实现代码,重点讲解推荐的Deque用法。

操作名称 功能描述 Stack方法 Deque推荐方法(栈模式) 栈空时行为
入栈 将元素压入栈顶 push(E e) push(E e) / offerFirst(E e) 无异常(容量足够时)
出栈 移除并返回栈顶元素 pop() pop() / pollFirst() pop抛异常;pollFirst返回null
查看栈顶 返回栈顶元素但不移除 peek() peek() / peekFirst() peek抛异常;peekFirst返回null
判空 判断栈是否为空 isEmpty() isEmpty() -
获取大小 返回栈中元素个数 size() size() -
清空栈 移除栈中所有元素 clear() clear() -
检查元素 判断栈中是否包含指定元素 contains(Object o) contains(Object o) -

二、代码示例(推荐Deque实现)

1. 基础操作示例(Deque + ArrayDeque)

ArrayDeque是Deque的数组实现,效率高于LinkedList,是栈的首选实现:

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

public class StackOperationsDemo {
    public static void main(String[] args) {
        // 1. 初始化栈(Deque作为栈使用,推荐ArrayDeque)
        Deque<Integer> stack = new ArrayDeque<>();

        // 2. 入栈(push)
        stack.push(1); // 栈:[1]
        stack.push(2); // 栈:[2, 1]
        stack.push(3); // 栈:[3, 2, 1]
        System.out.println("入栈后栈内容:" + stack); // 输出 [3, 2, 1](Deque打印顺序是头到尾,栈顶是头)

        // 3. 查看栈顶(peek)
        Integer topElement = stack.peek();
        System.out.println("栈顶元素:" + topElement); // 输出 3(栈顶不变)
        System.out.println("查看栈顶后栈内容:" + stack); // 输出 [3, 2, 1]

        // 4. 出栈(pop)
        Integer popElement = stack.pop();
        System.out.println("出栈元素:" + popElement); // 输出 3
        System.out.println("出栈后栈内容:" + stack); // 输出 [2, 1]

        // 5. 判空(isEmpty)
        boolean isEmpty = stack.isEmpty();
        System.out.println("栈是否为空:" + isEmpty); // 输出 false

        // 6. 获取栈大小(size)
        int size = stack.size();
        System.out.println("栈大小:" + size); // 输出 2

        // 7. 检查元素是否存在(contains)
        boolean contains = stack.contains(1);
        System.out.println("栈是否包含1:" + contains); // 输出 true

        // 8. 清空栈(clear)
        stack.clear();
        System.out.println("清空后栈是否为空:" + stack.isEmpty()); // 输出 true

        // 9. 安全出栈/查看(避免空栈异常)
        // pollFirst:栈空返回null,不抛异常(替代pop)
        Integer safePop = stack.pollFirst();
        System.out.println("空栈安全出栈:" + safePop); // 输出 null
        // peekFirst:栈空返回null,不抛异常(替代peek)
        Integer safePeek = stack.peekFirst();
        System.out.println("空栈安全查看栈顶:" + safePeek); // 输出 null
    }
}

2. 遗留类Stack的示例(了解即可,不推荐)

java.util.Stack是遗留类,继承自Vector,线程安全但性能差,且方法命名和Deque一致,示例如下:

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

public class LegacyStackDemo {
    public static void main(String[] args) {
        Stack<String> stack = new Stack<>();

        // 入栈
        stack.push("A");
        stack.push("B");

        // 查看栈顶
        System.out.println("栈顶:" + stack.peek()); // B

        // 出栈
        System.out.println("出栈:" + stack.pop()); // B

        // 判空
        System.out.println("是否为空:" + stack.isEmpty()); // false

        // 栈空时pop/peek会抛EmptyStackException
        stack.pop(); // 栈变为空
        // stack.pop(); // 抛EmptyStackException
    }
}

三、关键注意事项

  1. 空栈异常 :Stack.pop()/Stack.peek()、Deque.pop()/Deque.peek()在栈空时会抛出EmptyStackException/NoSuchElementException,推荐使用Deque.pollFirst()/Deque.peekFirst()(返回null,更安全);
  2. 线程安全 :Stack是线程安全的(基于Vector的同步方法),但效率低;ArrayDeque/LinkedList非线程安全,若需线程安全的栈,可使用Collections.synchronizedDeque(new ArrayDeque<>());
  3. Deque作为栈的规范 :Deque是双端队列,作为栈使用时,仅使用push()/pop()/peek()(等价于offerFirst()/removeFirst()/peekFirst()),避免使用队列相关方法(如add()/remove()),保证栈的LIFO规则。

总结

  1. Java栈核心操作包括入栈(push) 、出栈(pop) 、查看栈顶(peek) 、判空(isEmpty) 、获取大小(size) 、清空(clear) 等;
  2. 不推荐使用遗留类java.util.Stack,优先选择Deque接口(ArrayDeque/LinkedList)实现栈功能;
  3. 空栈操作时,优先使用pollFirst()/peekFirst()替代pop()/peek(),避免空指针异常,提升代码健壮性。
相关推荐
wang_shu_mo_ran5 小时前
MyBatis 从入门到进阶(一)
java·spring·mybatis
X1A0RAN6 小时前
PPT 图片批量处理教程:导出全部幻灯片 · 提取全部素材
开发语言·javascript·powerpoint
量化分析码农7 小时前
股票历史数据的复权参数对照:多级别返回的字段与数值差异
java·javascript·后端
猫猫不是喵喵.7 小时前
从0到1创建一个微服务项目
java·数据库·微服务·1024程序员节
熊猫钓鱼>_>7 小时前
普通用户视角的端侧智能体验手记【鸿蒙心迹】
开发语言·人工智能·华为·智能手机·性能优化·ai编程·harmonyos
瑞雪兆丰年兮7 小时前
JavaWeb-day13-SpringBootWeb事务管理&AOP
java·开发语言·springboot·javaweb·事务·web·aop
曲径海盗7 小时前
Try-Except怎么用,3个追问解答在自动化下的应用
java·jvm·oracle
Cosolar8 小时前
极简智库:快速搭建你的开源项目教程阅读平台,让 docs/ 目录被更多人看见
java·架构·github
nice_lcj5208 小时前
【从零理解 Spring AI · 16】Agent 与工作流:什么该写死,什么该让模型决定
java·人工智能·后端·spring ai·ai应用开发
布莱克6059 小时前
Swift 常量详解:从 let 到编译期优化
服务器·开发语言·ssh·swift·常量·let