Java的栈(Stack)

栈的特性

与队列(Queue)的"先进先出(FIFO)"不同,栈(Stack)是一种遵循后进先出(LIFO,Last In First Out) 原则的数据结构。可以形象地理解为一叠盘子:最后放上的盘子总是最先被拿走。

Java中栈的方法

Java标准库中并没有专门的Stack接口,而是通过Deque(双端队列)来模拟栈的功能。这是因为Java早期提供的Stack类是一个遗留类,存在设计缺陷,不推荐使用。

栈操作 Deque方法 等效方法
压栈 push(E e) addFirst(E e)
出栈 pop() removeFirst()
查看栈顶 peek() peekFirst()

使用Deque作为栈时,尽可能只调用push()pop()peek()方法,避免使用Deque的其他方法,以保证代码的清晰性。

栈的典型应用场景

1. 方法调用栈

JVM(Java虚拟机)使用栈来管理方法调用:

  • 每次调用方法时,JVM会将方法参数、返回地址等信息压入栈中
  • 方法执行完毕后,这些信息会被出栈,程序回到调用点继续执行

如果方法嵌套调用层数过深(如无限递归),会导致栈溢出,抛出StackOverflowError

public class StackOverflowExample {
public static void main(String[] args) {
recursiveCall();
} static void recursiveCall() {
recursiveCall(); // 无限递归导致栈溢出
}
}

2. 进制转换

栈非常适合实现整数的进制转换。以十进制转十六进制为例,算法步骤如下:

  1. 将整数除以目标进制(如16),得到商和余数
  2. 将余数压栈
  3. 用商重复步骤1,直到商为0
  4. 将栈中元素依次出栈,组成转换后的字符串

实现代码:

import java.util.Deque;
import java.util.LinkedList; public class HexConverter {
public static String toHex(int n) {
if (n == 0) {
return "0";
} Deque<Character> stack = new LinkedList<>();
char[] hexDigits = "0123456789ABCDEF".toCharArray(); while (n != 0) {
int remainder = n % 16;
stack.push(hexDigits[remainder]);
n = n / 16;
} StringBuilder sb = new StringBuilder();
while (!stack.isEmpty()) {
sb.append(stack.pop());
} return sb.toString();
} public static void main(String[] args) {
System.out.println(toHex(12500)); // 输出30D4
}
}

3. 表达式计算

栈是编译原理中处理表达式的重要工具,主要用于:

  • 将中缀表达式(如1 + 2 * (9 - 5))转换为后缀表达式(如1 2 9 5 - * +
  • 计算后缀表达式的值

计算后缀表达式的步骤:

  1. 扫描表达式,遇到数字则压栈
  2. 遇到运算符则弹出栈顶两个元素,计算结果后将结果压栈
  3. 表达式扫描完毕后,栈中剩余的元素即为计算结果

示例:计算1 2 9 5 - * +

import java.util.Deque;
import java.util.LinkedList; public class PostfixCalculator {
public static int calculate(String[] tokens) {
Deque<Integer> stack = new LinkedList<>(); for (String token : tokens) {
switch (token) {
case "+":
int b = stack.pop();
int a = stack.pop();
stack.push(a + b);
break;
case "-":
b = stack.pop();
a = stack.pop();
stack.push(a - b);
break;
case "*":
b = stack.pop();
a = stack.pop();
stack.push(a * b);
break;
case "/":
b = stack.pop();
a = stack.pop();
stack.push(a / b);
break;
default:
stack.push(Integer.parseInt(token));
}
} return stack.pop();
} public static void main(String[] args) {
String[] postfix = {"1", "2", "9", "5", "-", "*", "+"};
System.out.println(calculate(postfix)); // 输出9
}
}

总结

  • 掌握栈的特性和主要操作方法:压栈(push)、出栈(pop)和查看栈顶(peek)
  • 在Java中,我们使用Deque接口及其实现类(如LinkedListArrayDeque)来模拟栈。
  • 栈有广泛应用,
  • 栈在计算机科学中应用广泛,包括JVM方法调用、进制转换、表达式计算等场景。

Java集合——13.使用Stack的更多相关文章

  1. Java 集合系列 06 Stack详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  2. Java 集合系列 13 WeakHashMap

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  3. Java 集合系列 09 HashMap详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  4. Java 集合系列 10 Hashtable详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  5. Java 集合系列 17 TreeSet

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  6. Java 集合系列 16 HashSet

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  7. Java 集合系列 15 Map总结

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  8. Java 集合系列 14 hashCode

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  9. Java 集合系列 12 TreeMap

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  10. Java 集合系列 11 hashmap 和 hashtable 的区别

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

随机推荐

  1. gcc、g++命令

    gcc 与 g++ 分别是 gnu 的 c & c++ 编译器 gcc/g++ 在执行编译工作的时候,总共需要4步: 1.预处理,生成 .i 的文件[预处理器cpp] 2.将预处理后的文件转换 ...

  2. 我们不可能永远都在救火 ——Scrum中技术债务“偿还”指南

    技术债务是指开发人员为了加速软件开发,在应该采用最佳方案时进行了妥协,改用了短期内能加速软件开发的方案,以至于未来给自己带来额外的开发负担. 软件工程师 Ward Cunningham首次将技术的复杂 ...

  3. 现在的AI工具还能写剧本杀了?

    本文由 ChatMoney团队出品 近年来,剧本杀作为一种新兴社交游戏,收到了越来越多人的喜爱,它不仅需要玩家们发挥自身演技,还需运用逻辑思维推理,分析所获得的线索,找出案件真凶.然而你是否想过,你在 ...

  4. Spring注解中@Resource和@Authwired的区别

    Spring注解中@Resource和@Authwired的区别 @Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 by ...

  5. 看PHP7底层源码与设计 读后感

    对PHP的理解 读完这本书以后,发现自己好像不会PHP,自己知识PHP代码的搬运工,对数组的实现,内存管理,生命周期,垃圾回收,面向对象,Zend虚拟机这些知识点,这些都不知道,现在也说不上来,具体的 ...

  6. 【图书预售】清华大学出版社出版的《JMeter核心技术、性能测试与性能分析》开始预售了

    <JMeter核心技术.性能测试与性能分析>是一本由清华大学出版社出版的图书,JMeter是一款基于Java的压力测试工具,可用于对服务器.网络或对象模拟巨大的负载,在不同压力类别下测试它 ...

  7. 为什么PostgreSQL不自动缓存执行计划?这可能是最硬核的优化解读

    为什么PostgreSQL不自动缓存执行计划?这可能是最硬核的优化解读 前言 在数据库性能方面,查询语句的执行计划是最关键的因素之一.每当数据库接收到一个查询时,它必须决定如何以最有效的方式执行该查询 ...

  8. Sql server 游标处理数据

    https://blog.csdn.net/sinat_28984567/article/details/79811887 DECLARE @id INT , @name NVARCHAR(50) - ...

  9. 如何把数据库中的多个关联字段快速生成思维导图(excel如何将内容快速生成思维导图)

    本次记录绝对干货 一:要求 今天遇到的需求,又是一件费力的活,要求如下:数据库中有三个字段,分别是一级分类,二级分类,三级分类,三个字段是级别关系,三级分类一共有上百个,现要求用思维导图的方式展示出来 ...

  10. 在 django-ninja 中实现类似腾讯阿里云的应用鉴权机制

    前言 本文章介绍如何使用基于 AppClient 模型的 Django-Ninja API 鉴权机制. 这也是上次说的中台项目衍生物 中台项目相关的文章,我大概还会再写一篇 这个系列的文章注定是没什么 ...