如何轻松编写一个强大的字符串分解器-Java基础-Java-编程开发

AI智能体开发:从模型竞赛到系统工程,揭秘Nvidia“缰绳”框架设计 在AI智能体开发领域,大语言模型(LLM)和提示词工程是构建智能应用的基础技术。其核心原理在于通过自然语言指令引导模型完成复杂推理和任务规划。然而,仅依赖模型本身的能力往往难以保证智能体在真实场景中的稳定性和可靠性,其技术价值在于将AI从简单的对话交互升级为可执行多步任务、具备状态感知和错误恢复能力的自主系统。这要求开发者从系统工程角度出发,构建一套能够约束、引导和优化模型推理过程的框架。Nvidia提出的“缰绳”(Harness)概念正是这一思想的体现,它通过整合任务规划、状态管理、工具调用、反思循环和输 阅读详情
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

一、概述

大多数Java程序员都曾经使用过java.util.StringTokenizer类。它是一个很方便的字符串分解器,主要用来根据分隔符把字符串分割成标记(Token),然后按照请求返回各个标记。这个过程称为Tokenization,实际上就是把字符序列转换成应用程序能够理解的多个标记。

虽然StringTokenizer用起来很方便,但它的功能却很有限。这个类只是简单地在输入字符串中查找分隔符,一旦找到了分隔符就分割字符串。它不会检查分隔符是否在子串之中这类条件,当输入字符串中出现两个连续的分隔符时,它也不会返回""(字符串长度为0)形式的标记。

为了突破这些局限,Java 2平台提供了BreakIterator类,它是在StringTokenizer之上改进的字符串分解器。由于JDK 1.1.x没有提供这个类,为了满足自己的需要,开发者经常花费很多时间从头开始编写分解器。在涉及到数据格式化处理的大型工程中,这类定制的字符串分解器有时随处可见,而且这种情况并不罕见。

本文的目标是帮助你利用现有的StringTokenizer类,编写一个高级字符串分解器。

二、StringTokenizer的局限

你可以用以下三种构造函数中的任意一种创建StringTokenizer分解器:

StringTokenizer(String sInput):以空白字符( ,/t,/n)为分隔符分割字符串。

StringTokenizer(String sInput, String sDelimiter):以sDelimiter为分隔符分割字符串。

StringTokenizer(String sInput, String sDelimiter, boolean bReturnTokens):以sDelimiter为分隔符分割字符串,但如果bReturnTokens为true,则分隔符也作为标记返回。

第一个构造函数不检查输入字符串是否包含子串。例如,如果以空白字符为分隔符分割hello. Today /"I am /" going to my home town,则字符串分解结果是hello.、Today、"I、am、"、going等,而不是hello.、Today、"I am "、going等。

第二个构造函数不检查两个分隔符连续出现的情况。例如,如果以,为分隔符分割book, author, publication,,,date published这个字符串,则StringTokenizer返回book、author、publication和date published这四个标记,而不是book、author、publication、""、""和date published这6个标记(其中""表示0长度字符串)。要得到6个标记的答案,你必须把StringTokenizer的bReturnTokens参数设置为true。

允许设置值为true的bReturnTokens参数是一个重要的功能,因为它考虑到了分隔符连续出现的情况。例如,使用第二个构造函数时,如果数据是动态收集得到而且要用来更新数据库中的表,输入字符串中的标记对应着表里面列的值,那么当我们不能确定哪一个列应该设置为""时,我们就无法把输入串中的标记映射到数据库列。假设我们要把记录插入到一个有6个列的表,而输入数据中包含两个连续的分隔符。此时,StringTokenizer的分解结果是5个标记(两个连续的分隔符代表""标记,它将被StringTokenizer忽略),而我们却有6个字段需要设置。同时,我们也不知道连续分隔符在哪里出现,所以也就不知道哪一个列应该设置成""。

当标记本身等同于分隔符(无论是长度还是值)且位于子串之内时,第三个构造函数无效。例如,如果我们要以,为分隔符分解字符串book, author, publication,/",/",date published(这个字符串包含一个,标记,它与分隔符一样),结果是book、author、publication、"、"、date published这六个标记,而不是book、author、publication、,(逗号字符)、date published这五个标记。再提醒一下,即使我们把StringTokenizer的bReturnTokens参数设置设置成了true,在这种情况下也没有什么帮助。

三、高级字符串分解器

在编写代码之前,你必须搞清楚一个好的分解器有哪些基本要求。因为Java开发者已经习惯于使用StringTokenizer类,所以一个好的分解器应该提供StringTokenizer类提供的所有实用方法,比如hasMoreTokens()、nextToken()、countTokens()。

本文提供的代码很简单,而且大部分代码足以自我解释。在这里,我主要利用了StringTokenizer类(创建类实例时bReturnTokens参数设置为true),并提供了上面提到的几个方法。大多数时候标记与分隔符不同,有些时候分隔符却要作为标记输出(尽管非常罕见),此时如果出现了对标记的请求,分解器要把分隔符作为标记输出。创建PowerfulTokenizer对象时,你只需要提供输入字符串和分隔符这两个参数,PowerfulTokenizer将在内部使用bReturnTokens设置成true的StringTokenizer。(这么做的原因在于,如果不是用bReturnTokens设置成true的方式创建StringTokenizer,那么它将在解决先前提出的问题时受到限制)。为了正确地控制分解器,代码在几个地方(计算标记的总数量以及nextToken())检查bReturnTokens是否设置成了true。

你可能已经发现,PowerfulTokenizer实现了Enumeration接口,从而也就实现了hasMoreElements()和nextElement()这两个方法,而这两个方法又分别把调用直接委托给hasMoreTokens()和nextToken()。(由于实现了Enumeration接口,PowerfulTokenizer实现了与StringTokenizer的向后兼容。)

我们来看一个例子,假设输入字符串是hello, Today,,, /"I, am /", going to,,, /"buy, a, book/",分隔符是,。用分解器分割这个字符串时返回结果如表1所示:

表1:字符串分解结果

输入字符串包含11个逗号(,)字符,其中3个在子串里面、4个连续出现(Today,,,中包含两个连续逗号,第一个逗号是Today的分隔符)。下面是PowerfulTokenizer计算标记总数的算法:

如果bReturnTokens=true,把子串中的分隔符数量乘以2,再从实际总数量减去该数字,就得到了标记的总数。理由是,对于子串buy, a, book,StringTokenizer将返回5个标记(即buy:,:a:,:book),而PowerfulTokenizer将返回一个标记(即buy, a, book),两者的差值是4(即,2乘以子串中的分隔符数量)。这个公式对于所有包含分隔符的子串都有效。

类似地,对于bReturnTokens=false的情形,我们从实际总数(19)减去表达式[分隔符总数(11)- 连续分隔符数量(4) 子串中的分隔符数量(3)]。由于这时我们不返回分隔符,它们(非连续出现或在子串内部)对我们来说没有用,上面的公式为我们返回了标记的总数量(9)。

请记住这两个公式,它们是PowerfulTokenizer的核心。这两个公式适用于几乎所有它们各自条件下的情形。但是,如果你有更复杂的要求,不能使用这两个公式,那么你应该在编写代码之前分析各种可能出现的情况,并设计出自己的公式。

// 检查分隔符是否位于子串之内

for (int i=1; i/td>
{
iIndex = sInput.indexOf(sDelim, iIndex 1);
if (iIndex == -1)
break;
// 如果分隔符位于子串之内,则向前分析直至子串结束
while (sInput.substring(iIndex-iLen, iIndex).equals(sDelim))
{
iNextIndex = sInput.indexOf(sDelim, iIndex 1);
if (iNextIndex == -1)
break;
iIndex = iNextIndex;
}
aiIndex[i] = iIndex;
//System.out.println("aiIndex[" i "] = " iIndex);
if (isWithinQuotes(iIndex))
{
if (bIncludeDelim)
iTokens -= 2;
else
iTokens -= 1;
}
}

countTokens()方法检查子串是否包含双引号。如果包含,那么它减少总数并把索引值修改为字符串中下一个双引号出现的位置(如上面的代码片断所示)。如果bReturnTokens是false,那么它从总数减去输入字符串中出现的非连续分隔符的数量。

// 如发现多个连续的分隔符,则返回""作为标记

if ( (sPrevToken.equals(sDelim)) && (sToken.equals(sDelim)) ) {
sPrevToken = sToken;
iTokenNo ;
return "";
}
// 检查标记本身是否等于分隔符
if ( (sToken.trim().startsWith("/"")) && (sToken.length() == 1) ) {
// 标记本身等于分隔符的特殊情况
String sNextToken = oTokenizer.nextToken();
while (!sNextToken.trim().endsWith("/"")) {
sToken = sNextToken;
sNextToken = oTokenizer.nextToken();
}
sToken = sNextToken;
sPrevToken = sToken;
iTokenNo ;
return sToken.substring(1, sToken.length()-1);
}
// 检查字符串中是否包含子串
else if ( (sToken.trim().startsWith("/""))
&& (!((sToken.trim().endsWith("/""))
&& (!sToken.trim().endsWith("/"/"")))) )
{
if (oTokenizer.hasMoreTokens())
{
String sNextToken = oTokenizer.nextToken();
// 检查"/"/""
while (!((sNextToken.trim().endsWith("/""))
&& (!sNextToken.trim().endsWith("/"/""))) )
{
sToken = sNextToken;
if (!oTokenizer.hasMoreTokens())
{
sNextToken = "";
break;
}
sNextToken = oTokenizer.nextToken();
}
sToken = sNextToken;
}
}
nextToken()方法通过StringTokenizer.nextToken方法获取标记,并检查标记中的双引号字符。如果发现了这些字符,它继续获取标记直至不能再找到带有双引号的标记。另外,它还把标记保存到一个变量(sPrevToken,参见本文后面完整的源代码)以检查连续出现的分隔符。如果nextToken()发现等同于分隔符的连续多个标记,那么它返回""(长度为0的字符串)作为标记。

按照类似的方法,hasMoreTokens()方法检查已经返回的标记数量是否小于标记的总数量。

【结束语】本文为你介绍了如何轻松地编写一个强大的字符串分解器。根据本文介绍的原理,你能够迅速编写出复杂的字符串分解器,节省大量的开发时间。

SpringBoot+Vue+MySQL 高校学科竞赛平台 完整可运行版(源码+文档) 本项目基于SpringBoot+Vue+MySQL构建高校学科竞赛管理平台,覆盖学生、教师、领队教师、管理员四大角色,实现竞赛发布、报名、刷题、评分、公示等全流程闭环管理。系统架构清晰,技术主流,配套完整源码、数据库脚本、万字论文、开题报告、答辩PPT及部署文档,支持一键运行,适用于毕业设计、课程设计及院系二次开发,真正实现“开箱即用”。 阅读详情

相关推荐

Langchain与Milvus集成中的pymilvus.exceptions.MilvusException: channel not found错误解析

本文深入解析了在Langchain与Milvus集成时常见的pymilvus.exceptions.MilvusException: channel not found错误。该错误通常由客户端配置错误、网络问题、服务端状态异常或版本不兼容导致。文章提供了从基础连通性测试到高级网络排查的完整故障排除指南,并针对本地Docker、远程服务器及Kubernetes等典型部署场景给出了具体解决方案,帮助开发者快速定位并修复这一连接层问题。

weixin_29229989的博客 217

StringTokenizer字符分解器

yaoguicheng的专栏 739

基于 YOLO + SAM 的自动图像标注实战

摘要: 本文提出一种基于YOLO检测和SAM分割的自动化数据标注流水线方案,通过YOLO定位目标并生成检测框,再以检测框为提示驱动SAM完成精细分割,最终输出YOLO格式的标注文件。该方案将人工标注升级为半自动流程,显著提升标注效率,尤其适用于多类别、大规模图像的实例级标注需求。代码模块化设计支持模型灵活替换,并集成异常处理与进度可视化功能。虽依赖YOLO检测质量且对小目标存在局限,但作为工程落地方案,可有效降低私有数据集构建成本,适用于工业检测、遥感等场景的冷启动标注。

qq_64366203的博客 1147

分解和合并:Java 也擅长轻松的并行编程!

作者:Julien Ponge Java SE 7 提供的新分解/合并任务如何使编写并行程序变得更轻松? 2011 年 7 月发布 下载: Java SE 7 示例代码 (Zip) 多核处理器现在已广泛应用于服务器、台式机和便携机硬件。它们还扩展到到更小的设备,如智能电话和平板电脑。由于进程的线程可以在多个内核上并行执行,因此多核处理器为并发编程打开了一扇扇新的大门。为实

hanxinis的专栏 878

HALCON 20.11实战:5步搞定工业图像异常检测(附完整代码)

本文提供了一份基于HALCON 20.11的工业图像异常检测实战指南。通过五个核心步骤——环境准备、数据预处理、模型训练、推理解析与工程化部署,详细演示了如何利用深度学习技术,仅使用正常样本快速构建并优化金属表面划痕等缺陷的检测模型,并附有完整可运行的HDevelop代码,助力工程师实现高效、智能的工业视觉质检。

weixin_29243279的博客 140

YOLOv8目标出入计数部署:讲解C#使用ONNX检测模型进行目标出入计数 可运行完整实例

代码、步骤、讲解完整,可一键运行,效果如下:车辆出入计数人员出入计数。

Limiiiing的博客 79

StringTokenizer字符串分解器

今天在旧source,看到这样一段代码,对StringTokenizer 很感兴趣,以前没见过,恰好做了个调查,请大家批评指正       StringTokenizer st = new StringTokenizer(key, ",", false);         while (st.hasMoreTokens()) {             if (userAgent.index

laoma4102的专栏 1万+

PyTorch深度学习实战(24)——使用U-Net架构进行图像分割

图像分割 (Image segmentation) 是计算机视觉领域中的一个重要任务,旨在将图像划分为具有语义信息的不同区域或对象。与目标检测任务不同,图像分割要求像素级别的精确定位和分类,将每个像素标记为属于哪个类别或属于哪个区域。在本节中,我们将介绍图像分割的基本概念,并训练一个基于 U-Net 架构的图像分割模型。

盼小辉丶的博客 1万+

javap - Java class文件分解器

javap是jdk自带的一个工具,可以反编译,也可以查看java编译器生成的字节码,是分析代码的一个好工具。 描述:   javap命令分解一个class文件,它根据options来决定到底输出什么。如果没有使用options,那么javap将会输出包,类里的protecte

徐辉的专栏 1066

卫星轨道坐标转换:轨道六根数到经纬高(经STK验证)

a:半长轴(km)e:偏心率i:轨道倾角(度)Ω:升交点赤经(度)ω:近地点幅角(度)ν:真近点角(度)

weixin_52370774的博客 170

Harness Engineering:让Coding Agent真正落地生产

本文将带你系统性地了解如何让Coding Agent真正落地生产,核心是依托(全球领先的持续交付、云成本管理、 feature flagging、安全治理一体化平台),结合企业级AIDD(AI-Driven Development)的工程化实践,构建一套可信赖、可观测、可扩展、可治理的Coding Agent落地体系。核心概念与理论基础:什么是Coding Agent?它和普通的AI代码补全工具(比如GitHub Copilot)有什么区别?什么是Harness Engineering?

移动开发前沿的博客 456

java实现数字拆解(正整数的所有拆解结果)

题目:将一个正整数进行拆解,最大数不能超过2. 打印可拆解情况和所有拆解结果。解题思路:用递归来实现。

Lilyの博客 ٩(❛ัᴗ❛ั) 6838

基于STM32设计的水下水质检测装置(微信小程序)(205)

本项目设计了一款基于STM32微控制器为核心的水下水质检测设备,该设备具有高度集成化、智能化的特点,能够实时监测水深、温度、浊度及溶解性总固体(TDS)等关键水质参数,并通过4G网络将数据上传至腾讯云IOT物联网平台,实现远程监控和数据分析。同时,为了便于操作和移动观测,还配套开发了微信小程序,用户可通过微信小程序实时查看并控制设备的各项功能,如调整下潜深度等。

1252

从Prompt Engineering到Loop Engineering:构建AI自主编程的智能循环系统

在人工智能驱动的软件开发领域,Prompt Engineering(提示工程)是指导大语言模型生成代码的核心技术,它通过精心设计的指令来引导模型输出。其原理在于将开发者的意图转化为模型可理解的上下文,从而生成、补全或修改代码。这项技术的价值在于显著提升了代码生成的初始准确性和效率,成为人机协作编程的基础。随着模型能力的增强,单纯依赖单次指令交互已无法应对复杂、多步骤的软件开发任务,其应用场景逐渐从一次性代码生成扩展到需要持续迭代和验证的自动化流程。这自然催生了更高级的范式——Loop Engineering

weixin_34269583的博客 393

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

类分解器JavaP--分析Java字节码

转自: http://www.comprg.com.cn/detail.asp?hw_id=2632 深入Java编程——Java的字节代码 Java程序员很少注意程序的编译结果。事实上,Java的字节代码向我们提供了非常有价值的信息。特别是在调试排除Java性能问题时, 编译结果让我们可以更深入地理解如何提高程序执行的效率等问题。其实JDK使我们研究Java字节代码变得非常...

跑向经分的新手 538

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Java学习笔记 (六) Java常用命令 javap java class文件分解器

什么是javap,以及javap的用处 javap是java class文件分解器,可以反编译java class文件。 javap命令格式 javap &lt;options&gt; &lt;classes&gt; 首先,写个java类。。。。。如下图: public class HelloWorld{ static int i=1; ...

叶自飘零水自流的的博客 1635

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

InnoDB 内存结构总览:Change Buffer、AHI 与 Log Buffer

本文系统梳理InnoDB内存结构中的ChangeBuffer、Adaptive Hash Index(AHI)与LogBuffer。ChangeBuffer缓存二级索引页不在内存时的变更,减少随机IO,仅在页加载时合并;聚簇索引修改立即执行,因数据本身不可延后。AHI基于高频等值查询自动构建哈希索引,加速定位,仅支持等值操作。LogBuffer为redo log内存缓冲,配合磁盘日志实现崩溃恢复。三者均服务于性能优化,其中ChangeBuffer与AHI共享BufferPool空间,而LogBuffer独立

bksczm的博客 289

V8 机制、手写核心函数与 TypeScript 类型体操

或固定初始化(如数组先定长、对象先给全字段)保持类型与形状稳定;这些都比"换框架"更基础。只能处理纯数据(丢函数、Date、RegExp、循环引用报错)。生产级深拷贝要处理:原始值短路、循环引用、V8(Chrome / Node 的 JS 引擎)不是"解释一行跑一行"那么简单,它用。图:V8 执行流程——解释执行 + 热点优化,优化失败会 Deopt 回退。JS 内存自动管理,但"自动"不等于"不会漏"。是"固定间隔最多执行一次"。手写 Promise 是"懂异步"的试金石。是"停下后才执行最后一次",

qq_38468358的博客 346

Spring Boot 数据源与 MyBatis(-Plus) 自定义配置详解

本文详解 Spring Boot 中单数据源环境下 HikariCP 与 MyBatis-Plus 的自定义配置。通过手动声明 SqlSessionFactory,实现下划线转驼峰、日志输出、一级缓存策略等精细化控制。结合 HikariCP 核心参数调优(如最大连接数、连接生命周期),确保高性能与稳定性。适用于仅需访问单一数据库的场景,避免多数据源复杂性,兼顾性能与可维护性。

BADAO_LIUMANG_QIZHI的博客 198

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

要努力去发光,而不是被照亮~ 130

【从零理解 Spring AI · 12】MCP 的两种角色:做客户端还是做服务端

上一篇讲了 MCP 的概念:标准协议、三大角色、M+N 替代 M×N。

nice_lcj520的博客 501

LeetCode Hot 100 二叉树专题(二)3 题(Java)

本篇文章共 3 题:543. 二叉树的直径、102. 二叉树的层序遍历、108. 将有序数组转换为二叉搜索树。 每道题都统一按「① 题目分析 & 解题思路 → ② 常见解法(附代码)及讲解 → ③ 知识点总结」的顺序组织;代码使用 Java 编写,节点定义沿用 LeetCode 默认的 TreeNode。

2401_88612756的博客 365

JDK 下载安装:装完 Java 提示「不是内部或外部命令」?环境变量没配

JDK 是写 Java 程序必须装的东西。它包含运行 Java 的虚拟机(JRE)和编译 Java 的编译器(javac)——装了它,能跑、.java文件能编译成可执行程序。免费,学习和小规模生产都不花钱。

科小怪的博客 635

java框架大全

java框架大全

qq_39326137的博客 183

Java 多态 学习笔记

多态是面向对象编程的重要特性,指同一操作作用于不同对象时产生不同行为。其核心在于“父类引用指向子类对象”,结合方法重写实现运行时动态绑定。多态使代码更灵活、可扩展,如用Person p = new Student();统一处理各类人员注册,无需修改调用逻辑。但多态无法直接调用子类特有方法,需通过instanceof判断并强制转换。编译时看左边(类型),运行时看右边(实际对象),实现解耦与维护便利。

AA_AA114514的博客 361

SecureRandom做随机源,这个Java随机字符串工具类有3个方法

本文分享一款JDK17环境下的Java随机字符串工具类,内置3个开箱即用的方法,全部采用SecureRandom加密安全随机源,不存在弱随机、可预测、取模偏差等问题。工具类支持默认62字符集随机串、纯数字随机串、自定义字符集随机串三种生成模式,支持Unicode码点级别的字符集处理,兼容Emoji等增补字符,边界处理严格,异常信息明确,适合验证码、邀请码、盐值、随机口令、短链码等场景,源码可直接复制使用。

Java后端 | AI智能体应用实战派 | 电脑技能行家 299
上一篇: Java中正则表达式使用方法详解-Java基础-Java-编程开发
下一篇: 该学Java或.NET?-Java基础-Java-编程开发
java169
博客等级 码龄18年 27粉丝 2568原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值