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 对象。

posted on 2025-12-10 09:17  coding博客  阅读(0)  评论(0)    收藏  举报