replaceAll
replaceAll 是 Java String 类的一个实例方法,用于替换字符串中所有匹配正则表达式的子串。

方法签名:
public String replaceAll(String regex, String replacement)
参数说明:
regex: 你要查找的正则表达式,这是replaceAll与replace最关键的区别。replacement: 用于替换匹配项的字符串。
返回值:
- 返回一个新字符串,它是通过将当前字符串中所有匹配
regex的子串替换为replacement得到的。 - 如果没有匹配项,则返回原字符串。
replaceAll vs. replace
初学者最容易混淆 replaceAll 和 replace 方法,它们的主要区别在于第一个参数的类型。

| 特性 | replaceAll(String regex, String replacement) |
replace(char/Sequence old, char/Sequence new) |
|---|---|---|
| 第一个参数 | 正则表达式 | 普通字符或字符序列 |
| 功能 | 查找所有匹配正则表达式的模式,并替换 | 查找指定的普通字符或子串,并替换 |
| 示例 | str.replaceAll("\\d", "x") |
str.replace('1', 'x') |
replace:处理字面量,你想找什么,就精确地找什么。replaceAll:处理模式,你可以使用强大的正则表达式来定义你要找的规则。
常见陷阱与解决方案
陷阱1:忘记转义正则表达式的特殊字符
正则表达式中有一些特殊字符,如 (匹配任意字符), (匹配0个或多个), (匹配1个或多个), (匹配0个或1个), (行尾), \d (数字) 等。
问题场景: 我想把字符串中的所有点 替换成 。
错误示范:

String text = "www.example.com";
// 错误! "." 在正则表达式中表示“任意字符”,而不是字面上的点
String result = text.replaceAll(".", "-");
// 结果是 "---------",因为每个字符都被替换了
System.out.println(result);
正确做法:
在正则表达式中,使用反斜杠 \ 来转义特殊字符,在 Java 字符串中,反斜杠本身也是一个特殊字符,所以需要用两个反斜杠 \\ 来表示一个字面上的反斜杠。
String text = "www.example.com";
// 正确! "\\." 表示匹配一个字面上的点 "."
String result = text.replaceAll("\\.", "-");
// 结果是 "www-example-com"
System.out.println(result);
其他需要转义的字符示例:
- ->
\\* - ->
\\+ - ->
\\? - ->
\\( - ->
\\)
陷阱2:在 replacement 字符串中错误使用引用符
replacement 参数也支持特殊的序列,主要用于引用正则表达式中的捕获组。
$1,$2, ...: 引用第一个、第二个捕获组匹配的内容。$&: 引用整个匹配的子串。`$': 引用匹配子串之前的所有内容。`$': 引用匹配子串之后的所有内容。
问题场景: 我想在每个单词前后加上 word: 和 。
String text = "hello world";
// 错误!"$" 是特殊字符,不能直接这样用
String result = text.replaceAll("\\w+", "$word: :$");
// 会抛出异常:IllegalArgumentException: Illegal group reference
正确做法:
如果你想在 replacement 中使用字面上的 符号,你需要用反斜杠 \ 对其进行转义。
String text = "hello world";
// 正确!使用 "\\$" 来表示一个字面上的 "$"
String result = text.replaceAll("\\w+", "word: :");
// 结果是 "word: :word: :"
System.out.println(result);
使用捕获组的正确示例:
假设我们想把 name:John,age:30 这样的字符串变成 John (30)。
String text = "name:John,age:30";
// (\\w+) 是一个捕获组,匹配 "name" 和 "age"
// (\\d+) 是第二个捕获组,匹配 "John" 和 "30"
String result = text.replaceAll(".*?:(\\w+),.*?:(\\d+)", "$1 ($2)");
// 结果是 "John (30)"
System.out.println(result);
实用示例
示例1:移除所有数字和标点符号
String text = "Hello! My phone number is 123-456-7890.";
// \\d 匹配所有数字
// [^a-zA-Z\\s] 匹配所有非字母和非空白字符
String result = text.replaceAll("[^a-zA-Z\\s]", "");
// 结果是 "Hello My phone number is "
System.out.println(result);
示例2:规范化空白字符
将一个或多个连续的空白字符(空格、制表符、换行符等)替换为一个空格。
String text = "This is a\ntest\twith many whitespaces.";
// \\s+ 匹配一个或多个空白字符
String result = text.replaceAll("\\s+", " ");
// 结果是 "This is a test with many whitespaces."
System.out.println(result);
示例3:脱敏手机号
保留前3位和后4位,中间用 替换。
String phone = "13812345678";
// (\\d{3}) 匹配并捕获前3位
// (\\d{4}) 匹配并捕获后4位
String maskedPhone = phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
// 结果是 "138****5678"
System.out.println(maskedPhone);
示例4:替换换行符
在不同操作系统中,换行符可能不同(Windows: \r\n, Linux/Unix: \n),我们可以统一替换成 \n。
String text = "Line 1\r\nLine 2\nLine 3";
// \\r\\n 匹配 Windows 风格的换行符
String result = text.replaceAll("\\r\\n", "\n");
// 结果是 "Line 1\nLine 2\nLine 3"
System.out.println(result);
性能考虑
对于简单的、非正则表达式的替换,replace 方法通常比 replaceAll 更快,因为它不需要编译正则表达式。
- 如果只是替换固定字符串:始终优先使用
replace。 - 如果需要基于模式(如“所有数字”、“所有空白”)进行替换:必须使用
replaceAll或其他基于正则表达式的方法(如replaceFirst)。
| 方法 | 描述 | 关键点 |
|---|---|---|
replaceAll |
使用正则表达式替换所有匹配项 | regex 参数需要转义特殊字符,replacement 中的 需要转义。 |
replace |
替换所有字面量匹配项 | 参数是普通字符或字符串,性能通常更好。 |
replaceAll 的核心是正则表达式,理解这一点并注意转义问题,你就能熟练地使用它了。
