当前位置: 首页 > article >正文

Java字符串处理

Java字符串处理全解析:String、StringBuilder与StringBuffer

一、String类基础

1. String的本质

  • 不可变对象:Java中的String对象一旦创建就不能修改
  • 底层实现:基于private final char value[]字符数组
  • 字符串池:JVM维护的特殊存储区域,用于存储字符串字面量

2. 创建String对象的两种方式

// 方式1:字面量创建(直接存入字符串池)
String s1 = "Hello";// 方式2:new创建(堆内存新建对象)
String s2 = new String("Hello");

3. 字符串比较

String a = "Java";
String b = "Java";
String c = new String("Java");System.out.println(a == b);      // true(指向字符串池同一对象)
System.out.println(a == c);      // false(不同对象)
System.out.println(a.equals(c)); // true(内容相同)

4. 常用方法

方法说明示例
length()获取长度"abc".length() → 3
charAt()获取指定位置字符"abc".charAt(1) → ‘b’
substring()截取子串"Hello".substring(1,3) → “el”
indexOf()查找字符位置"Java".indexOf('a') → 1
toLowerCase()转小写"Java".toLowerCase() → “java”
toUpperCase()转大写"Java".toUpperCase() → “JAVA”
trim()去除首尾空格" Java ".trim() → “Java”
split()分割字符串"a,b,c".split(",") → [“a”,“b”,“c”]
replace()替换字符"Java".replace('a','o') → “Jovo”

二、StringBuilder与StringBuffer

1. 可变字符串类比较

特性StringStringBuilderStringBuffer
可变性不可变可变可变
线程安全
性能中等
使用场景少量操作单线程大量操作多线程大量操作

2. StringBuilder核心方法

StringBuilder sb = new StringBuilder();// 链式调用
sb.append("Java").append(" is").append(" awesome!");
System.out.println(sb); // "Java is awesome!"sb.insert(5, "really ");  // 插入
sb.delete(5, 12);        // 删除
sb.replace(0, 4, "Kotlin"); // 替换
sb.reverse();             // 反转

3. StringBuffer线程安全示例

class BufferThread extends Thread {private StringBuffer buffer;public BufferThread(StringBuffer buffer) {this.buffer = buffer;}@Overridepublic void run() {for(int i=0; i<100; i++){buffer.append(i);}}
}public class ThreadSafeDemo {public static void main(String[] args) throws InterruptedException {StringBuffer buffer = new StringBuffer();Thread t1 = new BufferThread(buffer);Thread t2 = new BufferThread(buffer);t1.start();t2.start();t1.join();t2.join();System.out.println("最终长度: " + buffer.length()); // 正确输出200}
}

三、性能对比实验

1. 字符串拼接测试

public class PerformanceTest {static final int LOOP_COUNT = 100000;public static void stringTest() {long start = System.currentTimeMillis();String s = "";for(int i=0; i<LOOP_COUNT; i++){s += "a";}System.out.println("String耗时: " + (System.currentTimeMillis()-start) + "ms");}public static void builderTest() {long start = System.currentTimeMillis();StringBuilder sb = new StringBuilder();for(int i=0; i<LOOP_COUNT; i++){sb.append("a");}System.out.println("StringBuilder耗时: " + (System.currentTimeMillis()-start) + "ms");}public static void bufferTest() {long start = System.currentTimeMillis();StringBuffer sb = new StringBuffer();for(int i=0; i<LOOP_COUNT; i++){sb.append("a");}System.out.println("StringBuffer耗时: " + (System.currentTimeMillis()-start) + "ms");}public static void main(String[] args) {stringTest();    // 约4500msbuilderTest();  // 约5msbufferTest();    // 约10ms}
}

2. 内存占用分析

// 使用jvisualvm观察内存变化
public class MemoryDemo {public static void main(String[] args) throws InterruptedException {System.out.println("开始测试...");Thread.sleep(10000);  // 等待连接VisualVM// String会产生大量中间对象String s = "";for(int i=0; i<100000; i++){s += i;}// StringBuilder只创建一个对象StringBuilder sb = new StringBuilder();for(int i=0; i<100000; i++){sb.append(i);}Thread.sleep(10000);  // 观察内存变化}
}

四、字符串最佳实践

1. 选择策略

  • String:少量操作、字符串常量、作为方法参数
  • StringBuilder:单线程环境下大量字符串操作
  • StringBuffer:多线程环境下大量字符串操作

2. 优化技巧

// 不好的写法
String result = "";
for(String str : stringList) {result += str;  // 每次循环创建新String对象
}// 好的写法
StringBuilder builder = new StringBuilder();
for(String str : stringList) {builder.append(str);
}
String result = builder.toString();

3. 字符串常量池优化

// 推荐写法(利用字符串池)
String s1 = "Hello";  
String s2 = "Hello";  // 复用s1对象// 不推荐写法(创建多余对象)
String s3 = new String("Hello");  // 强制创建新对象

五、扩展知识

1. 字符串压缩(Java 9+)

Java 9后String底层改用byte[]存储,并添加了编码标志字段:

// 查看字符串编码方式
String str = "你好Java";
Field field = String.class.getDeclaredField("coder");
field.setAccessible(true);
byte coder = (byte) field.get(str);
System.out.println(coder);  // 0表示Latin-1,1表示UTF-16

2. 字符串拼接底层优化

// Java编译器会自动优化为StringBuilder
String s = "a" + "b" + "c";
// 编译后等价于:
String s = new StringBuilder().append("a").append("b").append("c").toString();

3. 正则表达式应用

// 验证邮箱格式
String email = "test@example.com";
String regex = "^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$";
boolean isValid = email.matches(regex);// 提取数字
String text = "订单123金额456";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);
while(matcher.find()) {System.out.println("找到数字: " + matcher.group());
}

4. 字符串格式化

// 传统方式
String info1 = String.format("姓名: %s, 年龄: %d", "张三", 25);// Java 15+文本块
String json = """{"name": "%s","age": %d}""".formatted("李四", 30);

六、高级应用案例

1. 实现一个简单的模板引擎

public class TemplateEngine {private final String template;public TemplateEngine(String template) {this.template = template;}public String render(Map<String, Object> params) {StringBuilder result = new StringBuilder(template);for(Map.Entry<String, Object> entry : params.entrySet()) {String key = "${" + entry.getKey() + "}";String value = entry.getValue().toString();int index;while((index = result.indexOf(key)) != -1) {result.replace(index, index + key.length(), value);}}return result.toString();}public static void main(String[] args) {String template = "欢迎您,${user}!今天是${day}。";Map<String, Object> params = new HashMap<>();params.put("user", "王五");params.put("day", "2023-05-20");TemplateEngine engine = new TemplateEngine(template);System.out.println(engine.render(params));}
}

2. 字符串相似度比较

public class StringSimilarity {// 计算Levenshtein距离public static int levenshteinDistance(String a, String b) {int[][] dp = new int[a.length()+1][b.length()+1];for(int i=0; i<=a.length(); i++) dp[i][0] = i;for(int j=0; j<=b.length(); j++) dp[0][j] = j;for(int i=1; i<=a.length(); i++) {for(int j=1; j<=b.length(); j++) {int cost = (a.charAt(i-1) == b.charAt(j-1)) ? 0 : 1;dp[i][j] = Math.min(Math.min(dp[i-1][j]+1, dp[i][j-1]+1),dp[i-1][j-1]+cost);}}return dp[a.length()][b.length()];}// 计算相似度百分比public static double similarity(String a, String b) {int maxLen = Math.max(a.length(), b.length());if(maxLen == 0) return 1.0;return (1 - (double)levenshteinDistance(a,b)/maxLen) * 100;}public static void main(String[] args) {String s1 = "kitten";String s2 = "sitting";System.out.printf("相似度: %.2f%%", similarity(s1, s2));}
}

七、常见面试题解析

1. String为什么设计为不可变?

  • 安全性:作为参数传递时不会被意外修改
  • 线程安全:无需同步即可在多线程中使用
  • 缓存哈希:String常用作HashMap的key,hashCode可缓存
  • 字符串池:实现字符串常量池的基础

2. String s = new String(“xyz”)创建了几个对象?

  • 如果"xyz"不在字符串池中:2个(字符串池中1个,堆中1个)
  • 如果"xyz"已在字符串池中:1个(只在堆中创建新对象)

3. 如何高效拼接字符串数组?

// 使用StringJoiner(Java 8+)
StringJoiner sj = new StringJoiner(", ", "[", "]");
for(String str : array) {sj.add(str);
}
String result = sj.toString();// 或者直接使用String.join()
String result = String.join(", ", array);

4. 如何实现字符串反转?

// 方法1:使用StringBuilder
new StringBuilder(str).reverse().toString();// 方法2:字符数组交换
char[] chars = str.toCharArray();
for(int i=0, j=chars.length-1; i<j; i++,j--) {char temp = chars[i];chars[i] = chars[j];chars[j] = temp;
}
new String(chars);

八、总结与最佳实践

1. 关键点回顾

  • String是不可变对象,适合少量操作和作为常量
  • StringBuilder是可变、非线程安全的字符串操作类
  • StringBuffer是线程安全版本的StringBuilder
  • 大量字符串操作时应避免直接使用String

2. 性能优化建议

  1. 预分配StringBuilder容量:new StringBuilder(initialCapacity)
  2. 避免在循环中使用+拼接字符串
  3. 使用String.join()替代手动拼接分隔字符串
  4. 考虑使用CharSequence接口作为方法参数类型

通过深入理解Java字符串处理机制,开发者可以编写出更高效、更健壮的字符串处理代码,这对日常开发中的文本处理、数据格式化和系统间通信等场景至关重要。

相关文章:

Java字符串处理

Java字符串处理全解析&#xff1a;String、StringBuilder与StringBuffer 一、String类基础 1. String的本质 不可变对象&#xff1a;Java中的String对象一旦创建就不能修改底层实现&#xff1a;基于private final char value[]字符数组字符串池&#xff1a;JVM维护的特殊存储…...

JS实现RSA加密

目录 目标 环境 实现RSA加解密 计算RSA加密允许的最大字节长度 目标 使用JS实现RSA加密解密。计算RSA加密允许的最大字节长度。 环境 node-rsa 实现RSA加解密 const NodeRSA require(node-rsa);function getKey() {const keyLength512// 创建 RSA 密钥对const key new …...

MySQL GTID集合运算函数总结

MySQL GTID 有一些运算函数可以帮助我们在运维工作中提高运维效率。 1 GTID内置函数 MySQL 包含GTID_SUBSET、GTID_SUBTRACT、WAIT_FOR_EXECUTED_GTID_SET、WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS 4个内置函数&#xff0c;用于GTID集合的基本运算。 1.1 GTID_SUBSET(set1,set2) …...

从“链主”到“全链”:供应链数字化转型的底层逻辑

1. 制造业与供应链数字化转型的必然性 1.1. 核心概念与战略重要性 制造业的数字化转型&#xff0c;是利用新一代数字技术&#xff08;如工业互联网、人工智能、大数据、云计算、边缘计算等&#xff09;对制造业的整体价值链进行根本性重塑的过程。这不仅涉及技术的应用&#…...

学习笔记十五——rust柯里化,看不懂 `fn add(x) -> impl Fn(y)` 的同学点进来!

&#x1f9e0; Rust 柯里化从零讲透&#xff1a;看不懂 fn add(x) -> impl Fn(y) 的同学点进来&#xff01; &#x1f354; 一、什么是柯里化&#xff1f;先用一个超好懂的生活比喻 假设你在点一个汉堡&#xff1a; 你说&#xff1a;我要点一个鸡腿汉堡&#xff01; 店员…...

定制化突围:遨游防爆手机的差异化竞争策略

在石油、化工、矿山等危险作业场景中&#xff0c;随着工业智能化与安全生产需求的升级&#xff0c;行业竞争逐渐从单一产品性能的比拼转向场景化解决方案的深度较量。遨游通讯以九重防爆标准为技术底座&#xff0c;融合多模稳控系统与全景前瞻架构&#xff0c;开辟出"千行…...

【Java学习笔记】进制与进制转换

进制与进制转换 一、进制介绍 二进制&#xff1a;0、1&#xff0c;满 2 进 1&#xff0c;以 0b 或 0B 开头。 十进制&#xff1a;0-9&#xff0c;满 10 进 1。 八进制&#xff1a;0-7&#xff0c;满 8 进 1&#xff0c;以数字 0 开头表示。 十六进制&#xff1a;0-9 及 A(10…...

士兵乱斗(贪心)

问题 B: 士兵乱斗 - USCOJ...

【C++面向对象】封装(下):探索C++运算符重载设计精髓

&#x1f525;个人主页 &#x1f525; &#x1f608;所属专栏&#x1f608; 每文一诗 &#x1f4aa;&#x1f3fc; 年年岁岁花相似&#xff0c;岁岁年年人不同 —— 唐/刘希夷《代悲白头翁》 译文&#xff1a;年年岁岁繁花依旧&#xff0c;岁岁年年看花之人却不相同 目录 C运…...

JVM初探——走进类加载机制|三大特性 | 打破双亲委派SPI机制详解

目录 JVM是什么&#xff1f; 类加载机制 Class装载到JVM的过程 装载&#xff08;load&#xff09;——查找和导入class文件 链接&#xff08;link&#xff09;——验证、准备、解析 验证&#xff08;verify&#xff09;——保证加载类的正确性 准备&#xff08;Prepare&…...

[图论]Kruskal

Kruskal 本质&#xff1a;贪心&#xff0c;对边进行操作。存储结构&#xff1a;边集数组。适用对象&#xff1a;可为负权图&#xff0c;可求最大生成树。核心思想&#xff1a;最短的边一定在最小生成树(MST)上&#xff0c;对最短的边进行贪心。算法流程&#xff1a;对全体边集…...

UML-饮料自助销售系统(无法找零)序列图

一、题目&#xff1a; 在饮料自动销售系统中&#xff0c;顾客选择想要的饮料。系统提示需要投入的金额&#xff0c;顾客从机器的前端钱币口投入钱币&#xff0c;钱币到达钱币记录仪&#xff0c;记录仪更新自己的选择。正常时记录仪通知分配器分发饮料到机器前端&#xff0c;但可…...

Nginx Http配置整理

一、nginx 配置参数&#xff1a; server {#SSL 默认访问端口号为 443listen 443 ssl;#请填写绑定证书的域名server_name cloud.tencent.com; #请填写证书文件的相对路径或绝对路径ssl_certificate cloud.tencent.com_bundle.crt; #请填写私钥文件的相对路径或绝对路径ssl_cer…...

爬虫利器SpiderTools谷歌插件教程v1.0.0!!!web端JavaScript环境检测!!!

SpiderTools谷歌插件教程v1.0.0 一、SpiderTools简介二、下载通道三、插件介绍四、插件使用五、工具函数使用 一、SpiderTools简介 SpiderTools主要用于检测和监控网页的JavaScript运行环境。该插件可以帮助开发者更好地查看网页运行环境&#xff0c;特别是在处理复杂的前端环…...

计算机视觉算法实战——基于YOLOv8的农田智能虫情测报灯害虫种类识别系统开发指南

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​ ​​​​​​​​​ ​​ 一、智能虫情监测领域概述 1.1 农业虫害防治现状 全球每年因虫害造成的粮食损失达20%-40%&#xff0c;我…...

14-算法打卡-哈希表-基本概念-第十四天

1 基本概念 1.1 哈希表 百度百科解释&#xff1a; 散列表&#xff08;Hash table&#xff0c;也叫哈希表&#xff09;&#xff0c;是根据关键码值(Key value)而直接进行访问的数据结构。也就是说&#xff0c;它通过把关键码值映射到表中一个位置来访问记录&#xff0c;以加快…...

趣味编程之分布式系统:负载均衡的“雨露均沾“艺术

#此篇文章由Deepseek大力支持&#x1f60b; 凌晨三点&#xff0c;西二旗某火锅店后厨—— “羊肉卷走3号桌&#xff01;” “肥牛卷去7号&#xff01;” “虾滑优先给VIP区&#xff01;” 我蹲在传菜口的监控屏幕前&#xff0c;看着机器人服务生们忙而不乱地穿梭。突然间&am…...

第十六届蓝桥杯大赛软件赛省赛 C++ 大学 B 组 部分题解

赛时参加的是Python组&#xff0c;这是赛后写的题解&#xff0c;还有两题暂时还不会&#xff0c;待更新 题目链接题目列表 - 洛谷 | 计算机科学教育新生态 A 移动距离 答案&#xff1a;1576 C 可分解的正整数 Python3 import itertools from functools import cmp_to_ke…...

考研数据结构之顺序查找、折半查找与分块查找详解(包含真题及解析)

考研数据结构之顺序查找、折半查找与分块查找详解 一、顺序查找&#xff08;Sequential Search&#xff09; 1.1 基本思想 顺序查找是最基础的查找算法&#xff0c;通过遍历数据集合逐个比较目标值与当前元素&#xff0c;直到找到匹配项或遍历结束。其核心特点是&#xff1a…...

英文查重的时候参考文献显示重复是怎么回事?

像上图这样参考文献部分有颜色的情况&#xff0c;是属于参考文献没有排除干净的问题。 如何解决这样的问题&#xff1f; 首先第一步&#xff0c;先确认该报告是不是排除参考文献的版本&#xff1b; 第二步&#xff0c;如果是排除参考文献的版本&#xff0c;且参考文献仍然有…...

八股文---MySQl(3)

目录 12.事务的特性是什么&#xff1f;可以详细说一下吗&#xff1f; 回答 13并发事务带来哪些问题&#xff1f;怎么解决这些问题呢&#xff1f;MySQL的默认隔离级别是&#xff1f; 脏读&#xff1a;一个事务读到另外一个事务还没有提交的数据。 不可重复读&#xff1a;一个…...

基于labview的钢琴程序设计

部分程序如下 按照上图子vi更改输出频率即可 若需完整程序可以联系我...

国内网络设备厂商名单(List of Domestic Network Equipment Manufacturers)

国内网络设备厂商名单 运维工程师必须广泛熟悉国内外各大厂商的设备&#xff0c;深入掌握其应用场景、功能特点及优势。这不仅有助于在故障排查时迅速定位问题&#xff0c;还能在系统设计、优化与升级中做出更合理的决策。对设备特性的精准把握&#xff0c;能够显著提升运维效…...

基于CNN+ViT的蔬果图像分类实验

本文只是做一个简单融合的实验&#xff0c;没有任何新颖&#xff0c;大家看看就行了。 1.数据集 本文所采用的数据集为Fruit-360 果蔬图像数据集&#xff0c;该数据集由 Horea Mureșan 等人整理并发布于 GitHub&#xff08;项目地址&#xff1a;Horea94/Fruit-Images-Datase…...

高级语言调用C接口(五)结构体(3)-arkts

上一篇文章提到了&#xff0c;arkts和C接口之前还有一个Napi层&#xff0c;这层代码最大的优势就是C/C编码&#xff0c;这样&#xff0c;我们只需要把数据通过Json格式传递到Napi层&#xff0c;Napi层再定义一个结构体并赋值即可。arkts层是TypeScript代码&#xff0c;想定义成…...

【虚幻C++笔记】接口

目录 概述创建接口 概述 简单的说&#xff0c;接口提供一组公共的方法&#xff0c;不同的对象中继承这些方法后可以有不同的具体实现。任何使用接口的类都必须实现这些接口。实现解耦解决多继承的问题 创建接口 // Fill out your copyright notice in the Description page o…...

【MCP】第一篇:MCP协议深度解析——大模型时代的“神经连接层“架构揭秘

【MCP】第一篇&#xff1a;MCP协议深度解析——大模型时代的"神经连接层"架构揭秘 一、什么是MCP&#xff1f;二、为什么需要MCP&#xff1f;三、MCP的架构四、MCP与AI交互的原理4.1 ReAct&#xff08;Reasoning Acting&#xff09;模式4.2 Function Calling 模式 五…...

实时模式下 libaom 与 x264 编码对比实验

前沿 理论基础&#xff1a;在相同视频质量下&#xff0c;AV1的压缩率比H.264高约30%-50%。实时模式&#xff1a;视频编码中的实时模式&#xff0c;其核心目标是平衡编码效率与延迟要求&#xff0c;尤其在视频会议、直播、实时通信等场景中至关重要。 低延迟要求&#xff1a;编…...

学习海康VisionMaster之矩形检测

这几天太忙了&#xff0c;好几天没有学习了&#xff0c;今天终于空下来了&#xff0c;继续学习之路吧。 一&#xff1a;进一步学习了 今天学习下VisionMaster中的矩形检测&#xff0c;这个一开始我以为是形态学方面的检测&#xff0c;实际操作下来其实还是边缘直线的衍生应用&…...

解决前端vue项目在linux上,npm install,node-sass 安装失败的问题

Unable to save binary /var/lib/jenkins/workspace/xxx/node_modules/node-sass/vendor/linux-x64-72 : Error: EACCES: permission denied, mkdir ‘/var/lib/jenkins/workspace/x/node_modules/node-sass/vendor’ 这个是node-sass安装失败导致的。 #将npm的默认仓库更改为…...