字符串去重与统计:Java高效处理方法
小伙伴们对文章编程感兴趣吗?是否正在学习相关知识点?如果是,那么本文《字符串去重与字符统计:Java高效处理教程》,就很适合你,本篇文章讲解的知识点主要包括。在之后的文章中也会多多分享相关知识点,希望对大家的知识积累有所帮助!
1. 问题背景与目标
在字符串处理中,我们经常需要对字符串进行去重操作,即提取其中所有不重复的字符。更进一步,当面对一个字符串数组时,可能需要对数组中的每个字符串都进行去重,然后将这些去重后的字符串与一个目标字符串(也经过去重处理)进行比较,统计每个数组元素与目标字符串有多少个共同的去重字符。
例如,给定一个目标字符串 "iyee" 和一个字符串数组 ["hi", "bye", "bebe"]:
- 目标字符串去重后为 "iye"。
- 数组元素去重后为 ["hi", "bye", "be"]。
- 我们需要计算:
- "hi" 与 "iye" 的共同字符:'i',计数为 1。
- "bye" 与 "iye" 的共同字符:'y', 'e',计数为 2。
- "be" 与 "iye" 的共同字符:'e',计数为 1。 最终输出结果为 [1, 2, 1]。
2. 核心概念:字符串去重
字符串去重是本问题的基础。从一个字符串中提取所有不重复的字符,并按其首次出现的顺序组合成一个新的字符串。
2.1 使用 HashSet 实现字符去重
HashSet 是Java集合框架中用于存储不重复元素的优秀工具。我们可以遍历字符串的每个字符,尝试将其添加到 HashSet 中。如果 add 方法返回 true,说明该字符是首次出现,我们将其追加到结果 StringBuilder 中。
import java.util.HashSet; import java.util.Set; /** * 从给定字符串中提取所有不重复的字符,并按其首次出现的顺序返回。 * * @param s 待去重的字符串。 * @return 包含去重字符的新字符串。 */ public static String dist(String s) { StringBuilder sb = new StringBuilder(); Set<Character> set = new HashSet<>(); // 使用HashSet存储已遇到的字符 for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); // 如果字符首次添加到set中,则将其追加到结果字符串 if (set.add(c)) { sb.append(c); } } return sb.toString(); }
优点: 这种方法逻辑清晰,效率较高(HashSet 的 add 操作平均时间复杂度为 O(1))。 注意事项: 这种方法保留了字符首次出现的顺序。
2.2 替代方案:使用 Java 8 Stream API
Java 8 引入的 Stream API 提供了另一种简洁的去重方式:
import java.util.stream.Collectors; // ... (在同一个类中) public static String distWithStream(String s) { return s.chars() // 将字符串转换为IntStream,表示字符的ASCII值 .distinct() // 去除重复的字符 .mapToObj(c -> String.valueOf((char) c)) // 将int转换回char并包装为String .collect(Collectors.joining()); // 将所有字符连接成一个字符串 }
优点: 代码更简洁,更具函数式风格。 注意事项: distinct() 操作不保证保留原始字符的顺序。对于本问题,顺序不影响最终计数结果,因此两种 dist 方法均适用。通常,HashSet 的手动实现可能在性能上略优于 Stream 对于简单场景。在本教程中,我们将沿用 HashSet 的实现。
3. 数组元素去重与转换
在拥有了 dist 方法后,我们可以轻松地对字符串数组中的每个元素进行去重处理。
// 假设我们有一个字符串数组 a String[] a = {"hi", "bye", "bebe"}; String[] distinctArray = new String[a.length]; for (int i = 0; i < a.length; i++) { distinctArray[i] = dist(a[i]); // 对数组中的每个字符串调用去重方法 } // 此时 distinctArray 变为 ["hi", "bye", "be"]
4. 去重字符匹配与计数
这是问题的核心部分。我们需要比较两个去重后的字符串,计算它们之间有多少个共同的字符。
/** * 计算两个去重后的字符串有多少个共同字符。 * * @param s1 第一个去重字符串。 * @param s2 第二个去重字符串。 * @return 共同字符的数量。 */ public static int countCommonDistinctChars(String s1, String s2) { int count = 0; // 遍历其中一个字符串的每个字符 for (int i = 0; i < s1.length(); i++) { char c = s1.charAt(i); // 检查这个字符是否存在于另一个字符串中 if (s2.contains(String.valueOf(c))) { count++; } } return count; }
效率考量: String.contains() 方法在内部会进行线性搜索,其时间复杂度为 O(m),其中 m 是被搜索字符串的长度。如果 s1 和 s2 都非常长,且此操作需要频繁执行,可以考虑将其中一个字符串转换为 HashSet
5. 完整解决方案
将上述所有步骤整合到一个主方法中,即可得到完整的解决方案。
import java.util.HashSet; import java.util.Set; import java.util.Arrays; // 用于打印数组,方便测试 public class StringProcessor { /** * 从给定字符串中提取所有不重复的字符,并按其首次出现的顺序返回。 * * @param s 待去重的字符串。 * @return 包含去重字符的新字符串。 */ public static String dist(String s) { StringBuilder sb = new StringBuilder(); Set<Character> set = new HashSet<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (set.add(c)) { sb.append(c); } } return sb.toString(); } /** * 根据指定逻辑处理字符串和字符串数组: * 1. 对目标字符串 B 进行去重。 * 2. 对数组 a 中的每个字符串进行去重。 * 3. 计算去重后的数组元素与去重后的目标字符串 B 的共同字符数量。 * * @param b 目标字符串。 * @param a 字符串数组。 * @return 一个整数数组,包含每个数组元素与目标字符串的共同字符数量。 */ public static int[] mathProfessor(String b, String[] a) { // 1. 对目标字符串 B 进行去重 String distinctB = dist(b); // 2. 对数组 a 中的每个字符串进行去重,并存储到新数组中 String[] distinctArrayElements = new String[a.length]; for (int i = 0; i < a.length; i++) { distinctArrayElements[i] = dist(a[i]); } // 3. 计算共同字符数量并存储结果 int[] countResult = new int[a.length]; for (int i = 0; i < distinctArrayElements.length; i++) { int currentCount = 0; String currentElement = distinctArrayElements[i]; // 遍历去重后的目标字符串 B 的每个字符 for (int j = 0; j < distinctB.length(); j++) { char charFromB = distinctB.charAt(j); // 检查当前字符是否存在于去重后的数组元素中 if (currentElement.contains(String.valueOf(charFromB))) { currentCount++; } } countResult[i] = currentCount; } return countResult; } public static void main(String[] args) { String sampleB = "iyee"; String[] sampleA = {"hi", "bye", "bebe"}; int[] output = mathProfessor(sampleB, sampleA); System.out.println("Sample Input B: \"" + sampleB + "\""); System.out.println("Sample Input A: " + Arrays.toString(sampleA)); System.out.println("Sample Output: " + Arrays.toString(output)); // 预期输出: [1, 2, 1] String sampleB2 = "programming"; String[] sampleA2 = {"java", "python", "javascript", "go"}; int[] output2 = mathProfessor(sampleB2, sampleA2); System.out.println("\nSample Input B: \"" + sampleB2 + "\""); System.out.println("Sample Input A: " + Arrays.toString(sampleA2)); System.out.println("Sample Output: " + Arrays.toString(output2)); // distinctB = "progami" // distinctA2 = ["jav", "pytho", "javascrit", "go"] // "jav" vs "progami" -> 'a' -> 1 // "pytho" vs "progami" -> 'p', 'o' -> 2 // "javascrit" vs "progami" -> 'a', 'r', 'g', 'i' -> 4 // "go" vs "progami" -> 'g', 'o' -> 2 // Expected: [1, 2, 4, 2] } }
6. 注意事项与优化建议
字符集支持: 当前的 char 类型和 String.contains() 方法能够很好地处理大多数Unicode字符。如果需要处理更复杂的Unicode码点(例如代理对),可能需要更细致的字符迭代方式(如 s.codePoints())。但对于常见场景,现有方法已足够。
性能优化:
- 在 mathProfessor 方法的计数循环中,currentElement.contains(String.valueOf(charFromB)) 每次调用都会在 currentElement 中进行线性搜索。如果 distinctB 或 distinctArrayElements 中的字符串非常长,可以考虑将 currentElement 或 distinctB 转换为 HashSet
以优化查找效率。例如:
// 优化后的计数逻辑示例 // ... Set<Character> distinctBSet = new HashSet<>(); for (char c : distinctB.toCharArray()) { distinctBSet.add(c); } for (int i = 0; i < distinctArrayElements.length; i++) { int currentCount = 0; String currentElement = distinctArrayElements[i]; Set<Character> currentElementSet = new HashSet<>(); for (char c : currentElement.toCharArray()) { currentElementSet.add(c); } for (char charFromB : distinctBSet) { // 遍历Set,效率更高 if (currentElementSet.contains(charFromB)) { // Set查找平均O(1) currentCount++; } } countResult[i] = currentCount; } // ...
这种优化在字符串长度较大时效果显著,但会增加内存开销。对于本例中的短字符串,原始方案的简洁性可能更具优势。
- 在 mathProfessor 方法的计数循环中,currentElement.contains(String.valueOf(charFromB)) 每次调用都会在 currentElement 中进行线性搜索。如果 distinctB 或 distinctArrayElements 中的字符串非常长,可以考虑将 currentElement 或 distinctB 转换为 HashSet
代码可读性: 将去重逻辑封装在独立的 dist 方法中,极大地提高了主方法的清晰度和模块化程度,是良好的编程实践。
7. 总结
本教程提供了一个在Java中处理字符串去重和字符匹配计数的完整解决方案。通过 HashSet 有效地实现了字符串去重,并结合循环和 String.contains() 方法完成了字符匹配计数。文章不仅提供了可运行的代码示例,还讨论了潜在的性能优化方向和注意事项,帮助读者在实际开发中灵活应用这些技术。掌握这些字符串处理技巧,将有助于更高效地解决各类文本数据分析和处理问题。
以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于文章的相关知识,也可关注golang学习网公众号。

- 上一篇
- Word怎么画波浪线?简单教程分享

- 下一篇
- 联想电脑做PPT教程及操作指南
-
- 文章 · java教程 | 25分钟前 |
- Java商品库存管理实现全解析
- 102浏览 收藏
-
- 文章 · java教程 | 1小时前 |
- Java集成百度语音SDK实现语音识别教程
- 428浏览 收藏
-
- 文章 · java教程 | 1小时前 |
- Java字符串海明距离计算方法详解
- 130浏览 收藏
-
- 文章 · java教程 | 1小时前 |
- Java中this关键字详解
- 418浏览 收藏
-
- 文章 · java教程 | 1小时前 |
- StringBuilder与StringBuffer区别解析
- 433浏览 收藏
-
- 文章 · java教程 | 2小时前 |
- Java多if优化:三元运算符高效用法
- 211浏览 收藏
-
- 文章 · java教程 | 2小时前 |
- Java中this关键字的使用方法
- 492浏览 收藏
-
- 文章 · java教程 | 3小时前 |
- SpringBootActuator配置详解与使用指南
- 175浏览 收藏
-
- 文章 · java教程 | 3小时前 |
- Java开发记账本应用教程
- 387浏览 收藏
-
- 文章 · java教程 | 3小时前 | 命令行 Java版本 Java路径 java-version javac-version
- Java版本查看命令大全
- 153浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 499次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- PandaWiki开源知识库
- PandaWiki是一款AI大模型驱动的开源知识库搭建系统,助您快速构建产品/技术文档、FAQ、博客。提供AI创作、问答、搜索能力,支持富文本编辑、多格式导出,并可轻松集成与多来源内容导入。
- 457次使用
-
- AI Mermaid流程图
- SEO AI Mermaid 流程图工具:基于 Mermaid 语法,AI 辅助,自然语言生成流程图,提升可视化创作效率,适用于开发者、产品经理、教育工作者。
- 1237次使用
-
- 搜获客【笔记生成器】
- 搜获客笔记生成器,国内首个聚焦小红书医美垂类的AI文案工具。1500万爆款文案库,行业专属算法,助您高效创作合规、引流的医美笔记,提升运营效率,引爆小红书流量!
- 1273次使用
-
- iTerms
- iTerms是一款专业的一站式法律AI工作台,提供AI合同审查、AI合同起草及AI法律问答服务。通过智能问答、深度思考与联网检索,助您高效检索法律法规与司法判例,告别传统模板,实现合同一键起草与在线编辑,大幅提升法律事务处理效率。
- 1269次使用
-
- TokenPony
- TokenPony是讯盟科技旗下的AI大模型聚合API平台。通过统一接口接入DeepSeek、Kimi、Qwen等主流模型,支持1024K超长上下文,实现零配置、免部署、极速响应与高性价比的AI应用开发,助力专业用户轻松构建智能服务。
- 1342次使用
-
- 提升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浏览