0

0

java代码怎样实现栈的括号匹配功能 java代码栈应用场景的实现方法​

爱谁谁

爱谁谁

发布时间:2025-08-11 22:25:01

|

397人浏览过

|

来源于php中文网

原创

java中栈的典型应用场景包括函数调用管理、表达式求值、撤销/重做功能、浏览器历史记录和深度优先遍历;2. 实现后缀表达式求值器时,遍历表达式,数字压栈,运算符弹出两个操作数计算后将结果压栈,最终栈中唯一元素为结果;3. 使用栈时应优先选用deque接口的arraydeque实现而非stack类,避免同步开销,并注意检查栈空状态以防止异常,同时警惕递归导致的栈溢出错误,多线程环境下可选用并发安全的集合类,这些实践能提升性能与代码健壮性。

java代码怎样实现栈的括号匹配功能 java代码栈应用场景的实现方法​

在Java中,实现括号匹配功能,栈是不可或缺的利器。其核心思想在于,当遇到开括号时将其压入栈中,遇到闭括号时则尝试与栈顶的开括号进行配对。栈在Java编程中应用广泛,尤其擅长处理需要后进先出(LIFO)逻辑的场景,比如表达式求值、函数调用管理等。

解决方案

实现括号匹配,我通常会用Java的

java.util.Deque
接口,因为它比传统的
Stack
类更推荐,性能更好,也更灵活。

我的做法是:

立即学习Java免费学习笔记(深入)”;

  1. 遍历输入字符串,遇到左括号(
    (
    [
    {
    )就压栈。
  2. 遇到右括号,先检查栈是否为空。如果为空,那肯定是匹配失败了,比如多了一个右括号。
  3. 如果不为空,就弹出栈顶元素,看它是不是当前右括号对应的左括号。不是?失败。
  4. 遍历完所有字符后,如果栈里还有元素,说明有些左括号没被匹配,比如少了一个右括号,那也是失败。
  5. 最后,栈为空才算成功。

这是一个具体的实现示例:

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;

public class ParenthesisMatcher {

    public boolean isValid(String s) {
        // 使用ArrayDeque作为栈,比java.util.Stack更推荐
        Deque<Character> stack = new ArrayDeque<>();
        // 预设匹配规则,方便查找
        Map<Character, Character> mappings = new HashMap<>();
        mappings.put(')', '(');
        mappings.put('}', '{');
        mappings.put(']', '[');

        for (char c : s.toCharArray()) {
            if (mappings.containsKey(c)) { // 如果是右括号
                // 栈为空或栈顶元素不匹配,则无效
                if (stack.isEmpty() || stack.pop() != mappings.get(c)) {
                    return false;
                }
            } else { // 如果是左括号,压入栈中
                stack.push(c);
            }
        }

        // 遍历完所有字符后,如果栈为空,则所有括号都已匹配
        return stack.isEmpty();
    }

    // 可以在这里添加一个main方法测试
    public static void main(String[] args) {
        ParenthesisMatcher matcher = new ParenthesisMatcher();
        System.out.println("()[]{} is valid: " + matcher.isValid("()[]{}")); // true
        System.out.println("([{}]) is valid: " + matcher.isValid("([{}])")); // true
        System.out.println("(] is valid: " + matcher.isValid("(]"));         // false
        System.out.println("({[ is valid: " + matcher.isValid("({["));       // false
        System.out.println("}} is valid: " + matcher.isValid("}}"));         // false
        System.out.println(" is valid: " + matcher.isValid(""));             // true
    }
}

除了括号匹配,Java栈还有哪些典型应用场景?

除了括号匹配,栈在Java编程中扮演着多面手的角色。我个人觉得,最直观的莫过于它在计算机底层,特别是JVM中对函数调用的管理。每次方法调用,参数、局部变量、返回地址都会被压入一个“栈帧”中,方法执行完毕,栈帧弹出,这简直是LIFO的最佳写照。再比如,表达式求值,无论是将中缀表达式转换为后缀或前缀,还是直接计算后缀表达式,栈都能大显身手。还有那些我们日常离不开的“撤销/重做”功能,浏览器的前进/后退历史,甚至是图或树的深度优先遍历(DFS),栈都是其核心支撑结构。它提供了一种天然的顺序性,让那些需要反向处理或临时存储的逻辑变得清晰而高效。

如何在Java中实现一个基于栈的表达式求值器?

要说栈的实际应用,一个简单的后缀表达式求值器是个不错的例子。我们知道,后缀表达式(逆波兰表示法)的优点在于不需要括号就能明确运算顺序,非常适合用栈来处理。

Tome
Tome

先进的AI智能PPT制作工具

下载

其核心逻辑是:

  1. 遍历后缀表达式的每个元素。
  2. 如果是数字,就直接压入栈中。
  3. 如果是运算符,就从栈中弹出两个操作数(注意顺序,先弹出的通常是第二个操作数),执行运算,然后将结果再压回栈中。
  4. 表达式遍历完毕,栈中剩下的唯一元素就是最终结果。

这种模式非常简洁,避免了处理操作符优先级和括号的复杂性。

import java.util.ArrayDeque;
import java.util.Deque;

public class PostfixEvaluator {

    public int evaluate(String expression) {
        Deque<Integer> stack = new ArrayDeque<>();
        String[] tokens = expression.split(" "); // 假设数字和运算符用空格分隔

        for (String token : tokens) {
            if (token.matches("-?\d+")) { // 如果是数字(包括负数)
                stack.push(Integer.parseInt(token));
            } else { // 如果是运算符
                if (stack.size() < 2) {
                    throw new IllegalArgumentException("Invalid postfix expression: not enough operands for operator " + token);
                }
                int operand2 = stack.pop(); // 先弹出的作为第二个操作数
                int operand1 = stack.pop(); // 后弹出的作为第一个操作数
                int result;
                switch (token) {
                    case "+":
                        result = operand1 + operand2;
                        break;
                    case "-":
                        result = operand1 - operand2;
                        break;
                    case "*":
                        result = operand1 * operand2;
                        break;
                    case "/":
                        if (operand2 == 0) {
                            throw new ArithmeticException("Division by zero");
                        }
                        result = operand1 / operand2;
                        break;
                    default:
                        throw new IllegalArgumentException("Unknown operator: " + token);
                }
                stack.push(result);
            }
        }

        if (stack.size() != 1) {
            throw new IllegalArgumentException("Invalid postfix expression: too many operands or malformed");
        }
        return stack.pop();
    }

    public static void main(String[] args) {
        PostfixEvaluator evaluator = new PostfixEvaluator();
        System.out.println("3 4 + 5 * = " + evaluator.evaluate("3 4 + 5 *")); // (3+4)*5 = 35
        System.out.println("10 2 / = " + evaluator.evaluate("10 2 /"));     // 10/2 = 5
        System.out.println("5 1 2 + 4 * + 3 - = " + evaluator.evaluate("5 1 2 + 4 * + 3 -")); // 5 + ((1+2)*4) - 3 = 5 + 12 - 3 = 14
    }
}

使用Java栈时常见的陷阱与优化建议有哪些?

在Java里用栈,虽然概念简单,但有些地方还是得留心。

首先,我个人总是推荐用

java.util.Deque
接口的实现,比如
ArrayDeque
LinkedList
,来作为栈使用,而不是直接用
java.util.Stack
这个老旧的类。
Stack
Vector
的子类,继承了同步开销,而且API设计上有些不那么直观。
Deque
作为双端队列,提供了
push()
pop()
peek()
这些符合栈语义的方法,效率更高,也更符合现代Java的编程习惯。

其次,栈溢出(Stack Overflow)是个经典的错误。这通常不是数据结构本身的问题,而是指方法调用栈溢出,比如无限递归。虽然和我们这里讨论的数据结构栈是两回事,但在实际编程中,如果你的算法设计导致递归深度过大,或者在栈上分配了过多的局部变量,都可能触发这个错误。

再者,多线程环境下,如果你需要一个线程安全的栈,

Stack
类是同步的,但通常我们更倾向于使用
Collections.synchronizedList(new LinkedList<>())
ConcurrentLinkedDeque
等并发集合,它们提供了更细粒度的控制或更好的并发性能。如果不需要线程安全,
ArrayDeque
无疑是最佳选择。

最后,也是最基础的,任何时候对栈进行

pop()
peek()
操作之前,务必检查栈是否为空。否则,一个
EmptyStackException
就可能让你的程序崩溃。这些看似琐碎的细节,往往决定了代码的健壮性。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1567

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

241

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

150

2025.10.17

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1567

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

241

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

150

2025.10.17

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

760

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.4万人学习

如何进行WebSocket调试
如何进行WebSocket调试

共1课时 | 0.1万人学习

TypeScript全面解读课程
TypeScript全面解读课程

共26课时 | 5.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号