1. 概述
在本教程中,我们将探讨在 Java 中删除或替换字符串(String)部分内容的各种方法。
我们会先通过 String 类自带的 API 实现替换与删除操作,接着使用 StringBuilder 的 API 来处理,最后介绍 Apache Commons 库中的 StringUtils 工具类。
作为扩展,我们还会讨论一些常见的字符串替换问题,比如替换精确单词、删除字符直到某个特定字符等。
2. 使用 String API
最简单直接的方式是使用 String 类提供的 replace()
、replaceAll()
和 replaceFirst()
方法来替换子串。
其中 replace()
方法接受两个参数:目标字符串和替换字符串:
String master = "Hello World Baeldung!";
String target = "Baeldung";
String replacement = "Java";
String processed = master.replace(target, replacement);
assertTrue(processed.contains(replacement));
assertFalse(processed.contains(target));
上述代码的输出结果为:
Hello World Java!
如果需要使用正则表达式匹配目标内容,则应选择 replaceAll()
或 replaceFirst()
。顾名思义,replaceAll()
会替换所有匹配项,而 replaceFirst()
只替换第一个匹配项:
String master2 = "Welcome to Baeldung, Hello World Baeldung";
String regexTarget = "(Baeldung)$";
String processed2 = master2.replaceAll(regexTarget, replacement);
assertTrue(processed2.endsWith("Java"));
此时 processed2
的值为:
Welcome to Baeldung, Hello World Java
因为提供的正则表达式 (Baeldung)$
只匹配最后一个 “Baeldung”。
✅ 提示:以上所有示例中,我们都可以传入空字符串作为 replacement,从而实现“移除”目标字符串的效果。
3. 使用 StringBuilder API
除了 String 类外,我们还可以使用 StringBuilder 类来进行更灵活的字符串修改操作。它提供了 delete()
和 replace()
方法。
我们可以从已有字符串构造一个 StringBuilder 实例,然后进行操作:
String master = "Hello World Baeldung!";
String target = "Baeldung";
String replacement = "Java";
int startIndex = master.indexOf(target);
int stopIndex = startIndex + target.length();
StringBuilder builder = new StringBuilder(master);
接下来,使用 delete()
移除目标字符串:
builder.delete(startIndex, stopIndex);
assertFalse(builder.toString().contains(target));
也可以使用 replace()
替换目标字符串:
builder.replace(startIndex, stopIndex, replacement);
assertTrue(builder.toString().contains(replacement));
⚠️ 注意:与 String API 不同的是,使用 StringBuilder 需要手动计算目标子串的起始和结束索引。
4. 使用 StringUtils 工具类
Apache Commons Lang 库中的 StringUtils 提供了更多实用的字符串操作方法。
首先添加依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
最新版本可以在 Maven Repository 找到。
使用 StringUtils.replace()
替换字符串:
String master = "Hello World Baeldung!";
String target = "Baeldung";
String replacement = "Java";
String processed = StringUtils.replace(master, target, replacement);
assertTrue(processed.contains(replacement));
该方法还有一个重载版本,支持传入一个 max
参数,用于限制替换次数。
✅ 如果忽略大小写,可以使用 replaceIgnoreCase()
方法:
String master2 = "Hello World Baeldung!";
String target2 = "baeldung";
String processed2 = StringUtils.replaceIgnoreCase(master2, target2, replacement);
assertFalse(processed2.contains(target));
5. 替换精确单词
在实际开发中,我们可能只想替换字符串中的完整单词,而不是部分匹配的内容。
为此,可以使用正则表达式配合单词边界 \b
:
String sentence = "A car is not the same as a carriage, and some planes can carry cars inside them!";
String regexTarget = "\\bcar\\b";
String exactWordReplaced = sentence.replaceAll(regexTarget, "truck");
结果为:
"A truck is not the same as a carriage, and some planes can carry cars inside them!"
✅ 注意:Java 中的反斜杠必须转义,因此正则表达式中的 \b
写成 \\b
。
你也可以使用 Apache Commons 的 RegExUtils
类实现相同功能:
String regexTarget = "\\bcar\\b";
String exactWordReplaced = RegExUtils.replaceAll(sentence, regexTarget, "truck");
两种方式效果一致,选择哪个取决于你的项目依赖和使用习惯。
6. 删除字符直到指定字符
在真实项目中,我们有时需要从字符串中删除直到某个字符的内容。下面举两个例子说明“包含”与“不包含”目标字符的场景。
示例 1(包含目标字符):
static final String INPUT1 = "some prefix=Important Info: a=b";
我们的目标是删除从开头到第一个 =
的内容(包括 =
),得到:
Important Info: a=b
示例 2(不包含目标字符):
static final String INPUT2 = "some prefix<a, <b, c>>"
目标是删除到第一个 <
为止(不包括 <
),得到:
<a, <b, c>>
6.1. 使用 indexOf()
和 substring()
这是最直观的方法:
String result1 = INPUT1.substring(INPUT1.indexOf("=") + 1);
assertEquals("Important Info: a=b", result1);
✅ 说明:+1
是为了跳过 =
字符。
对于“不包含”的情况,去掉 +1
即可:
String result2 = INPUT2.substring(INPUT2.indexOf("<"));
assertEquals("<a, <b, c>>", result2);
6.2. 使用 split()
将字符串按分隔符切分为数组,取后半部分:
String result1 = INPUT1.split("=", 2)[1];
assertEquals("Important Info: a=b", result1);
对于“不包含”的情况,可以使用正向预查(lookahead):
String result2 = INPUT2.split("(?=<)", 2)[1];
assertEquals("<a, <b, c>>", result2);
6.3. 使用 replaceFirst()
通过正则表达式替换前缀部分:
String result1 = INPUT1.replaceFirst(".*?=", "");
assertEquals("Important Info: a=b", result1);
✅ 说明:.*?=
是非贪婪匹配,只匹配到第一个 =
。
或者使用字符类排除法:
result1 = INPUT1.replaceFirst("[^=]*=", "");
assertEquals("Important Info: a=b", result1);
对于“不包含”情况,只需去掉等号:
String result2 = INPUT2.replaceFirst("[^<]*", "");
assertEquals("<a, <b, c>>", result2);
7. 替换最后一次出现的文本
有时候我们需要替换字符串中最后一次出现的目标词,比如:
final static String INPUT3 = "The first word, the second word, the last word should be replaced.";
目标是将最后一个 “word” 替换为 “WORD”,得到:
final static String EXPECTED3 = "The first word, the second word, the last *WORD* should be replaced.";
7.1. 反转 + 替换 + 再反转
这个思路是:反转字符串,让最后一个变成第一个,然后使用 replaceFirst()
,最后再反转回来。
String reverseString(String input) {
return new StringBuilder(input).reverse().toString();
}
String theWord = "word";
String replacement = "*WORD*";
String reversedInput = reverseString(INPUT3);
String reversedTheWord = reverseString(theWord);
String reversedReplacement = reverseString(replacement);
String reversedResult = reversedInput.replaceFirst(reversedTheWord, reversedReplacement);
String result = reverseString(reversedResult);
assertEquals(EXPECTED3, result);
✅ 优点:思路清晰;缺点:多次反转,性能略差。
7.2. 使用 lastIndexOf()
方法
更直接的方式是使用 lastIndexOf()
定位最后一个出现位置,然后拼接前后部分:
String theWord = "word";
String replacement = "*WORD*";
int index = INPUT3.lastIndexOf(theWord);
String result = INPUT3.substring(0, index) + replacement + INPUT3.substring(index + theWord.length());
assertEquals(EXPECTED3, result);
✅ 推荐:这种方式更直观,性能更好。
8. 总结
在 Java 中删除或替换字符串部分内容有多种方式,各有优劣:
- ✅ 简单替换用
String.replace()
/replaceAll()
- ⚠️ 需要索引控制时用
StringBuilder
- ✅ 通用工具类推荐
StringUtils
- ✅ 复杂匹配推荐正则表达式
- ✅ 特定场景(如替换最后一个)推荐
lastIndexOf()
+ 拼接
完整代码示例可参考 GitHub 仓库:https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-string-algorithms-2