Java 字符串替换
字符串替换是 Java 开发中最高频的操作之一,比如数据脱敏、模板渲染、文本清洗、参数替换等场景都离不开它。Java 的
String类内置了多种替换方法,同时也支持正则表达式、批量替换等进阶操作。本文从基础方法到复杂场景,拆解字符串替换的核心用法与避坑要点。
一、核心替换方法:replace /replaceAll/replaceFirst
Java
String 类提供了 3 个核心替换方法,三者的核心区别在于是否支持正则表达式、替换范围,具体对比如下:| 方法名 | 匹配规则 | 替换范围 | 核心特点 |
|---|---|---|---|
replace() |
普通字符 / 字符串 | 所有匹配项 | 不支持正则,性能高 |
replaceAll() |
正则表达式 | 所有匹配项 | 支持复杂正则,需注意转义 |
replaceFirst() |
正则表达式 | 第一个匹配项 | 仅替换首次出现的匹配内容 |
1. 基础替换:replace ()(无正则,最常用)
replace() 有两个重载版本:replace(char oldChar, char newChar):替换所有指定字符;replace(CharSequence target, CharSequence replacement):替换所有指定字符串。
实例 1:替换单个字符
public class StringReplaceDemo {
public static void main(String[] args) {
String str = "Java is easy, Java is fun";
// 替换所有字符'a'为'A'
String result = str.replace('a', 'A');
System.out.println(result); // 输出:JAva is eAsy, JAva is fun
}
}
实例 2:替换字符串(非正则)
public class StringReplaceDemo {
public static void main(String[] args) {
String str = "2025-12-10";
// 替换所有"-"为"/"(即使传类似正则的字符串,也会当作普通文本)
String result = str.replace("-", "/");
System.out.println(result); // 输出:2025/12/10
}
}
关键注意:replace()不解析正则表达式!比如传入replace(".", "*"),会替换所有.字符,而非正则中的 “任意字符”。
2. 正则替换:replaceAll ()(匹配所有)
replaceAll() 支持正则表达式匹配,适合复杂规则的替换(如数字脱敏、格式转换)。*实例 1:数据脱敏(替换所有数字为)**
public class StringReplaceDemo {
public static void main(String[] args) {
String phone = "手机号:13812345678";
// 正则匹配所有数字(\\d),替换为*
String maskedPhone = phone.replaceAll("\\d", "*");
System.out.println(maskedPhone); // 输出:手机号:***********
}
}
实例 2:正则分组替换(日期格式转换)
public class StringReplaceDemo {
public static void main(String[] args) {
String date = "2025-12-10";
// 正则分组:(\d{4})匹配年,(\d{2})匹配月,(\d{2})匹配日,$1/$2/$3引用分组
String newDate = date.replaceAll("(\\d{4})-(\\d{2})-(\\d{2})", "$1/$2/$3");
System.out.println(newDate); // 输出:2025/12/10
}
}
实例 3:转义特殊字符(.、*、| 等)
正则中
.表示 “任意字符”,若需替换普通.,需用\\.转义,或用Pattern.quote()包裹目标字符串:public class StringReplaceDemo {
public static void main(String[] args) {
String str = "www.baidu.com";
// 错误:.匹配任意字符,会替换所有字符为-
// String wrong = str.replaceAll(".", "-");
// 正确:转义.,替换所有.为-
String correct1 = str.replaceAll("\\.", "-");
// 更安全:用Pattern.quote()自动转义
String correct2 = str.replaceAll(Pattern.quote("."), "-");
System.out.println(correct1); // 输出:www-baidu-com
System.out.println(correct2); // 输出:www-baidu-com
}
}
3. 局部替换:replaceFirst ()(仅替换第一个匹配项)
适合只需替换首次出现的内容,比如修正文本中第一个错误字符、提取首个参数等。
public class StringReplaceDemo {
public static void main(String[] args) {
String str = "a1b2c3d4";
// 仅替换第一个数字为*
String result = str.replaceFirst("\\d", "*");
System.out.println(result); // 输出:a*b2c3d4
// 替换首个逗号为分号
String text = "苹果,香蕉,橙子,葡萄";
String textResult = text.replaceFirst(",", ";");
System.out.println(textResult); // 输出:苹果;香蕉,橙子,葡萄
}
}
二、进阶场景:复杂替换需求
场景 1:忽略大小写替换
若需替换时忽略字符大小写(如把
AbC/ABC/abc都替换为xyz),可借助正则的(?i)标记(忽略大小写):public class StringReplaceDemo {
public static void main(String[] args) {
String str = "AbC123abc456ABC";
// (?i)标记忽略大小写,替换所有abc为xyz
String result = str.replaceAll("(?i)abc", "xyz");
System.out.println(result); // 输出:xyz123xyz456xyz
}
}
场景 2:模板参数批量替换
开发中常遇到 “{name} 你好,今天是 {date}” 这类模板,需批量替换占位符,可结合
Map+ 循环实现:import java.util.HashMap;
import java.util.Map;
public class TemplateReplaceDemo {
public static void main(String[] args) {
// 模板字符串
String template = "您好,{name}!您的订单{orderId}已发货,预计{date}送达。";
// 替换规则
Map<String, String> params = new HashMap<>();
params.put("{name}", "张三");
params.put("{orderId}", "JD12345678");
params.put("{date}", "2025-12-15");
// 批量替换
String result = template;
for (Map.Entry<String, String> entry : params.entrySet()) {
result = result.replace(entry.getKey(), entry.getValue());
}
System.out.println(result);
// 输出:您好,张三!您的订单JD12345678已发货,预计2025-12-15送达。
}
}
进阶优化:高频模板替换可使用 Apache Commons Text 的StrSubstitutor,简化代码:// 需引入依赖:org.apache.commons:commons-text:1.10.0 StrSubstitutor substitutor = new StrSubstitutor(params); String result = substitutor.replace(template);
场景 3:批量替换多个关键词
比如同时替换文本中的 “垃圾”“脏话” 等敏感词,用
Map存储替换规则,循环调用replace():import java.util.HashMap;
import java.util.Map;
public class MultiReplaceDemo {
public static void main(String[] args) {
String content = "这是垃圾内容,包含脏话!";
Map<String, String> sensitiveWords = new HashMap<>();
sensitiveWords.put("垃圾", "**");
sensitiveWords.put("脏话", "##");
String cleanContent = content;
for (Map.Entry<String, String> entry : sensitiveWords.entrySet()) {
cleanContent = cleanContent.replace(entry.getKey(), entry.getValue());
}
System.out.println(cleanContent); // 输出:这是**内容,包含##!
}
}
场景 4:空值 / 空字符串处理
替换空字符串或 null 为默认值,需先判空避免空指针:
public class EmptyReplaceDemo {
public static void main(String[] args) {
String str = ""; // 空字符串
String nullStr = null; // null
// 替换空字符串为默认值
String result1 = str.isEmpty() ? "默认值" : str;
System.out.println(result1); // 输出:默认值
// 替换null为默认值
String result2 = nullStr == null ? "默认值" : nullStr;
System.out.println(result2); // 输出:默认值
// 注意:replace("", "x")会在每个字符间插入x(慎用)
String test = "abc";
System.out.println(test.replace("", "x")); // 输出:xa xb xc x(实际是xaxbxcx)
}
}
三、避坑指南:常见错误与解决方案
1. 忽略 String 不可变性
String是不可变对象,所有替换方法都会返回新字符串,原字符串不会改变,必须接收返回值 // 错误示例:未接收返回值,原字符串不变
String str = "abc";
str.replace('a', 'x');
System.out.println(str); // 输出:abc
// 正确示例:接收返回值
String newStr = str.replace('a', 'x');
System.out.println(newStr); // 输出:xbc
2. 正则特殊字符未转义
使用
replaceAll()/replaceFirst()时,若目标字符串包含.*+?|()[]{}^$等正则特殊字符,未转义会导致替换结果异常:// 错误:|在正则中是“或”,会把"a|b"拆分为"a"或"b"
String str = "a|b|c";
String wrong = str.replaceAll("a|b", "*");
System.out.println(wrong); // 输出:*|*|c
// 正确:用Pattern.quote()转义
String correct = str.replaceAll(Pattern.quote("a|b"), "*");
System.out.println(correct); // 输出:*|c
3. 频繁替换导致性能问题
若需多次替换(如循环中替换),
String的不可变性会创建大量临时对象,建议改用StringBuilder:// 低效:多次创建String对象
String str = "a1b2c3d4";
for (int i = 0; i < 10; i++) {
str = str.replace(String.valueOf(i), "*");
}
// 高效:使用StringBuilder
StringBuilder sb = new StringBuilder("a1b2c3d4");
for (int i = 0; i < 10; i++) {
int index = sb.indexOf(String.valueOf(i));
while (index != -1) {
sb.replace(index, index+1, "*");
index = sb.indexOf(String.valueOf(i), index+1);
}
}
String result = sb.toString();
System.out.println(result); // 输出:a*b*c*d*
4. 空指针异常(NPE)
调用替换方法前,务必检查字符串是否为 null:
public static String safeReplace(String str, String oldStr, String newStr) {
if (str == null || oldStr == null || newStr == null) {
return str; // 或返回默认值
}
return str.replace(oldStr, newStr);
}
四、实战案例:数据脱敏(手机号 + 身份证号)
结合正则替换实现常见的脱敏需求:
public class DataMaskDemo {
// 手机号脱敏:保留前3后4,中间替换为****
public static String maskPhone(String phone) {
if (phone == null || !phone.matches("\\d{11}")) {
return phone; // 非11位手机号直接返回
}
return phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
}
// 身份证号脱敏:保留前6后4,中间替换为**********
public static String maskIdCard(String idCard) {
if (idCard == null || idCard.length() != 18) {
return idCard; // 非18位身份证直接返回
}
return idCard.replaceAll("(\\d{6})\\d{8}(\\d{4})", "$1**********$2");
}
public static void main(String[] args) {
System.out.println(maskPhone("13812345678")); // 输出:138****5678
System.out.println(maskIdCard("110101199001011234")); // 输出:110101**********1234
}
}
五、总结
Java 字符串替换的核心是根据场景选择合适的方法:
- 简单替换(字符 / 固定字符串):用
replace(),性能高且无需考虑正则; - 复杂规则替换(正则匹配):用
replaceAll()/replaceFirst(),注意特殊字符转义; - 批量 / 模板替换:结合
Map循环或第三方库(如 Apache Commons Text); - 高频替换:优先用
StringBuilder提升性能,避免频繁创建 String 对象。
浙公网安备 33010602011771号