Java字符串数字单词排序技巧
本文详细介绍了使用Java结合正则表达式和Stream API实现字符串单词数字排序的方法,旨在解决字符串乱序问题。通过巧妙运用正向先行和后行断言,将包含数字的字符串分割成“单词+数字”片段,并利用Map存储单词与数字的对应关系。文章重点讲解了如何利用`split()`方法和`Collectors.toMap()`函数,并强调了使用`TreeMap`保证排序的重要性,确保最终按数字顺序重组字符串。本文提供完整的示例代码,并针对代码可读性、维护性以及数字范围等问题提出了注意事项,助力开发者构建高效准确的字符串处理解决方案。
问题描述
在日常编程中,我们有时会遇到需要根据字符串中内嵌的数字来重新排列单词的需求。例如,给定字符串 "my1kiran4name2is3",其中每个单词后面都跟着一个数字(1-9),表示该单词在最终序列中的位置。我们的目标是根据这些数字,将单词重新排列为 "my name is kiran"。
示例:
- my 对应数字 1
- kiran 对应数字 4
- name 对应数字 2
- is 对应数字 3
按数字顺序排列后,结果应为:my (1) name (2) is (3) kiran (4)。
解决方案:基于正则表达式与 Stream API
解决此问题的一种高效方法是结合使用 Java 的正则表达式(特别是零宽断言)和 Stream API。这种方法能够优雅地将单词与数字分离,并进行后续处理。
核心思路
- 初始分割: 将整个字符串分割成“单词+数字”的片段(例如:"my1", "kiran4")。
- 二次分割与映射: 对每个片段,进一步将其分割为独立的单词和数字,并构建一个映射(Map),其中数字作为键,单词作为值。
- 排序与重组: 根据数字键的顺序,从映射中提取单词,并用空格连接起来形成最终的字符串。
步骤详解
我们将以字符串 "my1kiran4name2is3" 为例,逐步解释代码逻辑。
1. 初始分割:利用正向后行断言 ((?<=\\d))
第一步是将原始字符串根据数字进行分割,但要保留数字作为每个片段的结尾。这里使用正则表达式 (?<=\\d),它是一个正向后行断言(Positive Lookbehind)。这意味着它会匹配紧跟在一个数字 (\\d) 后面的位置,但不会将数字本身包含在匹配结果中。
String string = "my1kiran4name2is3"; // string.split("(?<=\\d)") 的结果是:["my1", "kiran4", "name2", "is3"]
经过这一步,我们得到了一个包含“单词+数字”形式的字符串列表。
2. 二次分割与映射:利用正向先行断言 ((?=\\d)) 并构建 Map
接下来,对上一步得到的每个片段(如 "my1"),我们需要将其进一步分割成单词和数字。这里使用 s.split("(?=\\d)"),(?=\\d) 是一个正向先行断言(Positive Lookahead)。它会匹配紧跟在一个数字 (\\d) 前面的位置,但同样不将数字本身包含在匹配结果中。这使得数字成为分割后的第二个元素。
// 以 "my1" 为例,s.split("(?=\\d)") 的结果是:["my", "1"] // 以 "kiran4" 为例,s.split("(?=\\d)") 的结果是:["kiran", "4"]
然后,我们使用 Stream API 的 collect(Collectors.toMap(...)) 方法将这些分割后的数组转换为一个 Map
Map<Integer, String> map = Arrays.asList(string.split("(?<=\\d)")) // 将分割结果转换为 List .stream() // 创建 Stream .map(s -> s.split("(?=\\d)")) // 对每个元素进行二次分割 .collect(Collectors.toMap(e -> Integer.parseInt(e[1]), e -> e[0])); // 最终得到的 map 可能是:{1="my", 4="kiran", 2="name", 3="is"} // 注意:HashMap 的迭代顺序不确定,下文会详细说明。
3. 重组字符串:连接 Map 中的值
最后一步是从 map 中提取单词并用空格连接。原始解决方案直接使用了 map.values().stream().collect(Collectors.joining(" "))。
string = map.values().stream() .collect((Collectors.joining(" "))); // 假设 map.values() 按键的顺序迭代,则结果为 "my name is kiran"
完整示例代码
import java.util.Arrays; import java.util.Map; import java.util.stream.Collectors; import java.util.TreeMap; // 导入 TreeMap 以确保排序 public class StringSorter { public static void main(String[] args) { String inputString = "my1kiran4name2is3"; System.out.println("原始字符串: " + inputString); // 步骤1 & 2: 分割并构建 Map Map<Integer, String> wordMap = Arrays.asList(inputString .split("(?<=\\d)")) // 第一次分割:["my1", "kiran4", "name2", "is3"] .stream() .map(s -> s.split("(?=\\d)")) // 第二次分割:[["my", "1"], ["kiran", "4"], ...] // 使用 TreeMap::new 确保 Map 内部按键排序 .collect(Collectors.toMap( e -> Integer.parseInt(e[1]), // 键:数字 e -> e[0], // 值:单词 (oldValue, newValue) -> oldValue, // 处理重复键(此处不应发生) TreeMap::new // 指定使用 TreeMap )); // 步骤3: 从 Map 中按键顺序提取值并连接 String sortedString = wordMap .values() // TreeMap 的 values() 方法会按键的自然顺序迭代 .stream() .collect(Collectors.joining(" ")); System.out.println("排序后的字符串: " + sortedString); } }
输出:
原始字符串: my1kiran4name2is3 排序后的字符串: my name is kiran
注意事项
代码可读性与维护性: 虽然上述解决方案利用了正则表达式和 Stream API 的强大功能,但其简洁性有时会牺牲一定的可读性,特别是对于不熟悉正则表达式零宽断言的开发者。在实际项目中,如果团队成员对这些高级特性不熟悉,可能需要添加详细注释或考虑更直观(尽管可能更冗长)的实现方式。
Map 的排序问题: 原始的 Collectors.toMap 默认创建的是 HashMap。HashMap 不保证元素的迭代顺序,这意味着 map.values().stream() 所产生的单词顺序可能不是按数字从小到大排列的。为了确保最终输出的单词严格按照数字顺序排列,应采取以下两种策略之一:
- 指定使用 TreeMap: 在 collect 阶段指定使用 TreeMap,如示例代码所示。TreeMap 会自动根据键的自然顺序(对于 Integer 来说就是数值大小)进行排序。 collect(Collectors.toMap(keyMapper, valueMapper, mergeFunction, TreeMap::new))
- 对 Map.Entry 进行排序: 如果必须使用 HashMap 或其他不保证顺序的 Map 实现,可以在获取值之前对 Map.Entry 进行排序: map.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(Map.Entry::getValue).collect(Collectors.joining(" ")); 本文提供的示例代码已采用第一种方法,通过指定 TreeMap::new 来保证最终输出的正确排序。
数字范围与格式: 本解决方案假设数字为单个数字(1-9)。如果字符串中的数字可能是多位数(例如 "word10"),则正则表达式 \\d 需要修改为 \\d+(匹配一个或多个数字),并且相应的 split 逻辑需要确保正确处理多位数字。例如,"word10" 使用 s.split("(?=\\d)") 仍会得到 ["word", "10"],所以对于多位数是兼容的。但如果数字前或后有其他字符,则需要更复杂的正则匹配。
总结
本教程详细展示了如何利用 Java 的正则表达式(特别是正向先行和后行断言)和 Stream API 来解决根据内嵌数字对字符串中单词进行排序的问题。通过将复杂的字符串处理分解为逻辑清晰的步骤:分割、映射和重组,并注意 Map 的排序特性,我们可以构建出既高效又准确的解决方案。在实际应用中,除了关注功能的实现,代码的可读性和健壮性(如处理不同数字范围和确保排序)同样至关重要。
以上就是《Java字符串数字单词排序技巧》的详细内容,更多关于的资料请关注golang学习网公众号!

- 上一篇
- 豆包AI宠物训练工具,让宠物更听话秘诀

- 下一篇
- 36漫画书单创建与分享教程
-
- 文章 · java教程 | 4小时前 |
- Java开发工业相机SDK教程详解
- 375浏览 收藏
-
- 文章 · java教程 | 4小时前 |
- Java构造方法使用详解
- 220浏览 收藏
-
- 文章 · java教程 | 6小时前 |
- Java类是什么?全面解析类的定义与结构
- 397浏览 收藏
-
- 文章 · java教程 | 6小时前 |
- SpringBoot集成Jedis实现缓存优化
- 488浏览 收藏
-
- 文章 · java教程 | 6小时前 |
- SpringSecurity验证码登录实现教程
- 248浏览 收藏
-
- 文章 · java教程 | 6小时前 |
- Java服务层数据映射与转换技巧
- 149浏览 收藏
-
- 文章 · java教程 | 6小时前 |
- SpringSecurity方法级控制全解析
- 501浏览 收藏
-
- 文章 · java教程 | 7小时前 |
- Java整合Solr实现全文检索配置教程
- 182浏览 收藏
-
- 文章 · java教程 | 7小时前 |
- 国际化错误提示设置方法详解
- 152浏览 收藏
-
- 文章 · java教程 | 7小时前 |
- Java连接InfluxDB操作指南
- 209浏览 收藏
-
- 文章 · java教程 | 8小时前 |
- Linux下Java环境配置详解
- 258浏览 收藏
-
- 文章 · java教程 | 8小时前 |
- Linux下Java环境配置全攻略
- 394浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 499次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 千音漫语
- 千音漫语,北京熠声科技倾力打造的智能声音创作助手,提供AI配音、音视频翻译、语音识别、声音克隆等强大功能,助力有声书制作、视频创作、教育培训等领域,官网:https://qianyin123.com
- 533次使用
-
- MiniWork
- MiniWork是一款智能高效的AI工具平台,专为提升工作与学习效率而设计。整合文本处理、图像生成、营销策划及运营管理等多元AI工具,提供精准智能解决方案,让复杂工作简单高效。
- 495次使用
-
- NoCode
- NoCode (nocode.cn)是领先的无代码开发平台,通过拖放、AI对话等简单操作,助您快速创建各类应用、网站与管理系统。无需编程知识,轻松实现个人生活、商业经营、企业管理多场景需求,大幅降低开发门槛,高效低成本。
- 521次使用
-
- 达医智影
- 达医智影,阿里巴巴达摩院医疗AI创新力作。全球率先利用平扫CT实现“一扫多筛”,仅一次CT扫描即可高效识别多种癌症、急症及慢病,为疾病早期发现提供智能、精准的AI影像早筛解决方案。
- 541次使用
-
- 智慧芽Eureka
- 智慧芽Eureka,专为技术创新打造的AI Agent平台。深度理解专利、研发、生物医药、材料、科创等复杂场景,通过专家级AI Agent精准执行任务,智能化工作流解放70%生产力,让您专注核心创新。
- 522次使用
-
- 提升Java功能开发效率的有力工具:微服务架构
- 2023-10-06 501浏览
-
- 掌握Java海康SDK二次开发的必备技巧
- 2023-10-01 501浏览
-
- 如何使用java实现桶排序算法
- 2023-10-03 501浏览
-
- Java开发实战经验:如何优化开发逻辑
- 2023-10-31 501浏览
-
- 如何使用Java中的Math.max()方法比较两个数的大小?
- 2023-11-18 501浏览