【Java原理系列】Java String类中的三个替换方法replaceFirst、replaceAll和replace原理用法示例源码详解

String类中的三个替换方法replaceFirst、replaceAll和replace原理用法示例源码详解

原理

这里是三种字符串替换方法的原理:

  • replaceFirst() 方法的原理是通过编译给定的正则表达式,然后使用编译后的模式创建一个匹配器对象,将该匹配器应用于目标字符串,并使用给定的替换字符串替换第一个匹配的子字符串。
  • replaceAll() 方法的原理与 replaceFirst() 类似,也是通过编译给定的正则表达式,创建一个匹配器对象,将其应用于目标字符串,并使用给定的替换字符串替换所有匹配的子字符串。
  • replace() 方法的原理是将目标字符串中的所有指定字符序列替换为另一个字符序列。它不使用正则表达式进行匹配,而是直接在目标字符串中搜索并替换目标字符序列。

这些方法都依赖于 java.util.regex.Pattern java.util.regex.Matcher 类来进行正则表达式的解析和匹配。 Pattern 类负责编译正则表达式,生成可供匹配使用的模式对象。 Matcher 类负责应用模式匹配器到目标字符串上,并执行替换操作。

当调用这些方法时,会按照指定的规则进行匹配和替换,并返回替换后的结果字符串。这些方法提供了灵活和强大的字符串替换功能,可以根据需要进行各种类型的替换操作。

用法

replaceFirst方法:

  1. 该方法使用给定的正则表达式进行匹配,并将第一个匹配到的子字符串替换为指定的替换字符串。
  2. 首先,通过Pattern.compile(regex)编译正则表达式,然后创建Matcher对象,并使用replaceFirst方法进行替换操作。
  3. 最终返回替换后的结果字符串。

replaceAll方法:

  1. 该方法与replaceFirst方法类似,但不仅替换第一个匹配到的子字符串,而是替换所有匹配到的子字符串。
  2. 同样,通过Pattern.compile(regex)编译正则表达式,创建Matcher对象,并使用replaceAll方法进行替换操作。
  3. 返回替换后的结果字符串。

replace方法:

  1. 该方法用于替换字符串中的目标字符序列(target)为指定的替换字符序列(replacement)。
  2. 首先,通过Pattern.compile(target.toString(), Pattern.LITERAL)编译目标字符序列,将其视为字面量进行匹配。
  3. 创建Matcher对象,并使用replaceAll方法进行替换操作。在替换过程中,使用Matcher.quoteReplacement方法对替换字符序列进行转义处理,以避免特殊字符的影响。
  4. 返回替换后的结果字符串。

这些替换方法提供了在字符串中进行模式匹配并替换的功能,可以根据需要选择合适的方法进行字符串的替换操作。

一般示例

public class StringReplaceExamples {
    public static void main(String[] args) {
        // 示例 1: 替换字符串中的单个字符
        String str1 = "Hello World";
        String replacedStr1 = str1.replace('o', 'O');
        System.out.println(replacedStr1); // 输出: HellO WOrld
        // 示例 2: 替换字符串中的子字符串
        String str2 = "Hello World";
        String replacedStr2 = str2.replace("World", "Universe");
        System.out.println(replacedStr2); // 输出: Hello Universe
        // 示例 3: 使用正则表达式替换字符串
        String str3 = "Hello, my name is John";
        String replacedStr3 = str3.replaceAll("John", "Alice");
        System.out.println(replacedStr3); // 输出: Hello, my name is Alice
        // 示例 4: 忽略大小写替换字符串
        String str4 = "Hello World";
        String replacedStr4 = str4.replaceAll("(?i)hello", "Hi");
        System.out.println(replacedStr4); // 输出: Hi World
        // 示例 5: 替换特殊字符
        String str5 = "Hello $ World";
        String replacedStr5 = str5.replace("$", "\\$");
        System.out.println(replacedStr5); // 输出: Hello \$ World
        // 示例 6: 替换单词边界处的字符串
        String str6 = "Hello Bob, welcome to Bob's World!";
        String replacedStr6 = str6.replaceAll("\\bBob\\b", "Alice");
        System.out.println(replacedStr6); // 输出: Hello Alice, welcome to Bob's World!
        // 示例 7: 删除字符串中的空格
        String str7 = "   Hello   World   ";
        String replacedStr7 = str7.replace(" ", "");
        System.out.println(replacedStr7); // 输出: HelloWorld
        // 示例 8: 使用引用替换匹配到的字符串
        String str8 = "Hello, my name is John Doe";
        String replacedStr8 = str8.replaceAll("John (Doe)", "Mr. $1");
        System.out.println(replacedStr8); // 输出: Hello, my name is Mr. Doe
        // 示例 9: 替换字符串中的数字
        String str9 = "Age: 25, Height: 180cm";
        String replacedStr9 = str9.replaceAll("\\d+", "*");
        System.out.println(replacedStr9); // 输出: Age: *, Height: *cm
        // 示例 10: 在匹配的子串前后添加特定字符
        String str10 = "apple, banana, cherry";
        String replacedStr10 = str10.replaceAll("(?<=, )", "-").replaceAll("(?=,)", "-");
        System.out.println(replacedStr10); // 输出: apple- banana- cherry
}

高级用法

1.正则表达式替换:

使用 replaceAll() 方法可以通过正则表达式来进行字符串替换。正则表达式可以匹配更复杂的模式,从而实现更精确的替换操作。

示例:

String str = "Hello, 123456!";
String replacedStr = str.replaceAll("\\d", "*");
System.out.println(replacedStr); // 输出: Hello, ****!

2.引用替换:

在替换字符串中,可以使用引用 $ 来引用正则表达式中匹配到的内容。这样可以在替换字符串中动态地插入匹配到的文本。

示例:

String str = "Hello, my name is John Doe";
String replacedStr = str.replaceAll("John (Doe)", "Mr. $1");
System.out.println(replacedStr); // 输出: Hello, my name is Mr. Doe

3.替换回调函数:

Java 8 中引入了 replaceAll() 方法的重载版本,该方法接受一个 Lambda 表达式作为替换参数。可以通过回调函数动态地生成替换字符串。

示例:

String str = "Hello World";
String replacedStr = str.replaceAll("o", m -> m.group().toUpperCase());
System.out.println(replacedStr); // 输出: HellO WOrld

4.使用预定义字符集和断言:

正则表达式中有一些预定义的字符集和断言,可以用于更精确的替换操作,如单词边界、行首和行尾等。

示例:

String str = "Hello, my name is John Doe";
String replacedStr = str.replaceAll("\\bJohn\\b", "Alice");
System.out.println(replacedStr); // 输出: Hello, my name is Alice Doe

5.替换特定位置的子串:

使用正则表达式中的捕获组和反向引用,可以在替换字符串中插入原始字符串的特定部分。

示例:

String str = "Hello, my name is John Doe";
String replacedStr = str.replaceAll("name is (\\w+)", "name is $1 Smith");
System.out.println(replacedStr); // 输出: Hello, my name is John Smith

6.使用替换回调函数进行逻辑处理:

通过编写自定义的替换逻辑,可以实现更复杂的字符串处理。这在需要根据匹配结果进行动态替换时非常有用。

示例:

String str = "Hello, today is 2022-02-15";
String replacedStr = str.replaceAll("\\d{4}-\\d{2}-\\d{2}", m -> {
    String date = m.group();
    int year = Integer.parseInt(date.substring(0, 4));
    int month = Integer.parseInt(date.substring(5, 7));
    int day = Integer.parseInt(date.substring(8, 10));
    String newDate = String.format("%02d-%02d-%02d", day, month, year);
    return newDate;
System.out.println(replacedStr); // 输出: Hello, today is 15-02-2022

7.字符串替换的性能优化:

对于大量的字符串替换操作,可以考虑使用 StringBuilder 或 StringBuffer 进行拼接,以提高性能。

示例:

String str = "Hello, World";
String replacedStr = str.replace("World", "Universe");
System.out.println(replacedStr); // 输出: Hello, Universe
// 使用 StringBuilder 进行拼接,提高性能
StringBuilder sb = new StringBuilder(str);
int index = sb.indexOf("World");
if (index != -1) {
    sb.replace(index, index + 5, "Universe");
replacedStr = sb.toString();
System.out.println(replacedStr); // 输出: Hello, Universe

这些高级用法可以帮助你更好地掌握字符串替换的技巧和方法。根据具体的需求,选择适当的方法和技术来实现复杂的字符串处理操作。

区别

这里是对字符串进行替换的三种方法的区别:

  • replaceFirst() 方法会替换 第一个与给定正则表达式匹配 的子字符串。例如,在字符串 "Hello World" 中,将第一个字母 "l" 替换为大写字母 "L",结果为 "HeLlo World"。
  • replaceAll() 方法会替换所有与 给定正则表达式匹配 的子字符串。例如,在字符串 "Hello World" 中,将所有字母 "l" 替换为大写字母 "L",结果为 "HeLLo WorLd"。
  • replace() 方法会替换指定的字符序列。它 不使用正则表达式 进行匹配,而是直接替换目标序列。例如,在字符串 "Hello World" 中,将所有字母 "o" 替换为大写字母 "O",结果为 "HellO WOrld"。

请注意, replaceFirst() replaceAll() 方法的参数是正则表达式,而 replace() 方法的参数是普通的字符序列。在替换过程中,如果替换字符串中包含特殊字符(如反斜杠和美元符号),可能会导致意外的结果。可以使用 Matcher.quoteReplacement() 方法来取消这些字符的特殊意义。

如何选择

选择使用哪种替换方法取决于你的需求和情况:

  • 如果你只想替换第一个匹配的子字符串,可以使用 replaceFirst() 方法。
  • 如果你想替换所有匹配的子字符串,可以使用 replaceAll() 方法。
  • 如果你要替换的是固定的字符序列,而不是根据正则表达式进行匹配,可以使用 replace() 方法。

除此之外,还需要考虑以下因素:

  • 正则表达式的复杂度:如果你需要使用复杂的正则表达式进行匹配,那么应该选择使用 replaceFirst() replaceAll() 方法。
  • 性能考虑:在处理大量字符串时, replace() 方法通常比正则表达式更高效。因为它不涉及正则表达式的解析和匹配过程。
  • 特殊字符的处理:如果你的替换字符串中包含特殊字符(如反斜杠和美元符号),可能会导致意外的结果。在这种情况下,你可以使用 Matcher.quoteReplacement() 方法来取消这些字符的特殊意义。

中文源码

/**
 * 使用给定的正则表达式替换此字符串中第一个与之匹配的子字符串。
 * 调用此方法的形式 <i>str</i>.replaceFirst(<i>regex</i>, <i>repl</i>) 生成的结果与表达式完全相同:
 * Pattern.compile(<i>regex</i>).matcher(<i>str</i>).replaceFirst(<i>repl</i>)
 * 注意,替换字符串中的反斜杠 (\) 和美元符号 ($) 可能导致结果与将其视为文字替换字符串时不同;
 * 参见 Matcher.replaceFirst。如果需要,请使用 Matcher.quoteReplacement 来取消这些字符的特殊意义。
 * @param regex       要匹配的正则表达式
 * @param replacement 要替换第一个匹配项的字符串
 * @return 结果字符串
 * @throws PatternSyntaxException 如果正则表达式的语法无效
 * @see java.util.regex.Pattern
 * @since 1.4
 * @spec JSR-51
public String replaceFirst(String regex, String replacement) {
    return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
 * 使用给定的正则表达式替换此字符串中与之匹配的每个子字符串。
 * 调用此方法的形式 <i>str</i>.replaceAll(<i>regex</i>, <i>repl</i>) 生成的结果与表达式完全相同:
 * Pattern.compile(<i>regex</i>).matcher(<i>str</i>).replaceAll(<i>repl</i>)
 * 注意,替换字符串中的反斜杠 (\) 和美元符号 ($) 可能导致结果与将其视为文字替换字符串时不同;
 * 参见 Matcher.replaceAll。如果需要,请使用 Matcher.quoteReplacement 来取消这些字符的特殊意义。
 * @param regex       要匹配的正则表达式
 * @param replacement 要替换每个匹配项的字符串
 * @return 结果字符串
 * @throws PatternSyntaxException 如果正则表达式的语法无效
 * @see java.util.regex.Pattern
 * @since 1.4
 * @spec JSR-51
public String replaceAll(String regex, String replacement) {
    return Pattern.compile(regex).matcher(this).replaceAll(replacement);
 * 使用指定的字面目标序列替换此字符串中与之匹配的每个子字符串。替换从字符串的开头到结尾进行,
 * 例如,在字符串 "aaa" 中用 "b" 替换 "aa" 将导致 "ba" 而不是 "ab"。
 * @param target      要替换的字符序列
 * @param replacement 替换的字符序列
 * @return 结果字符串