杰瑞科技汇

Java replace替换时,为何有时未生效?

replace 方法主要用于替换字符串中指定的字符或子字符串,Java 主要在 String 类和 StringBuilder/StringBuffer 类中提供了相关的 replace 方法,但它们的用法和效果有显著区别。

Java replace替换时,为何有时未生效?-图1
(图片来源网络,侵删)

String.replace() 方法

这是最常用、最安全的 replace 方法,它属于 不可变String 类,因此所有替换操作都会返回一个 新的字符串,而原始字符串保持不变。

String 类提供了两个重载的 replace 方法:

a) String.replace(char oldChar, char newChar)

  • 功能: 替换字符串中所有出现的 单个字符 oldCharnewChar
  • 参数:
    • oldChar: 需要被替换的旧字符。
    • newChar: 用于替换的新字符。
  • 返回值: 一个新的 String 对象,其中所有 oldChar 都被替换为 newChar
  • 特点: 区分大小写。

示例代码:

public class StringReplaceExample {
    public static void main(String[] args) {
        String str = "hello world, hello java";
        // 将所有 'l' 替换为 'p'
        String newStr = str.replace('l', 'p');
        System.out.println("原始字符串: " + str);      // 输出: hello world, hello java
        System.out.println("替换后字符串: " + newStr); // 输出: hepwo worpd, hep java
        // 替换不存在的字符
        String newStr2 = str.replace('z', 'x');
        System.out.println("替换不存在的字符: " + newStr2); // 输出: hello world, hello java (原样返回)
    }
}

b) String.replace(CharSequence target, CharSequence replacement)

  • 功能: 替换字符串中所有出现的 子字符串 targetreplacement
  • 参数:
    • target: 需要被替换的子字符串(CharSequence 接口,可以是 String)。
    • replacement: 用于替换的新子字符串(CharSequence 接口,可以是 String)。
  • 返回值: 一个新的 String 对象,其中所有 target 子串都被替换为 replacement 子串。
  • 特点: 区分大小写,这是 最常用replace 方法。

示例代码:

Java replace替换时,为何有时未生效?-图2
(图片来源网络,侵删)
public class StringReplaceSequenceExample {
    public static void main(String[] args) {
        String str = "I like Java, Java is powerful.";
        // 将所有 "Java" 替换为 "Python"
        String newStr = str.replace("Java", "Python");
        System.out.println("原始字符串: " + str);          // 输出: I like Java, Java is powerful.
        System.out.println("替换后字符串: " + newStr);     // 输出: I like Python, Python is powerful.
        // 替换一个不存在的子串
        String newStr2 = str.replace("C++", "Go");
        System.out.println("替换不存在的子串: " + newStr2); // 输出: I like Java, Java is powerful. (原样返回)
        // 注意:区分大小写
        String newStr3 = str.replace("java", "Kotlin");
        System.out.println("区分大小写: " + newStr3);      // 输出: I like Java, Java is powerful. (没有替换)
    }
}

StringBuilder.replace() / StringBuffer.replace() 方法

String 不同,StringBuilderStringBuffer可变 的,它们的 replace 方法会 直接修改当前对象,而不是返回一个新的对象。

  • 功能: 替换字符串中从指定 startend 索引范围内的内容。
  • 参数:
    • start: 开始替换的索引(包含)。
    • end: 结束替换的索引(不包含)。
    • str: 用于替换的新字符串。
  • 返回值: 返回 StringBuilderStringBuffer 对象本身,以便支持链式调用。
  • 特点: 直接修改原对象,效率高(对于大量字符串操作),但线程不安全(StringBuilder)或线程安全但性能稍差(StringBuffer)。

示例代码:

public class StringBuilderReplaceExample {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Hello World");
        // 将索引 6 到 11 (即 "World") 替换为 "Java"
        // 注意:replace的end索引是 exclusive (不包含) 的
        StringBuilder result = sb.replace(6, 11, "Java");
        System.out.println("原始 StringBuilder 对象: " + sb.toString());      // 输出: Hello Java
        System.out.println("replace方法的返回值: " + result.toString());     // 输出: Hello Java
        // 可以看到,原始对象 sb 和返回值 result 是同一个对象,并且内容已经被修改
        // 链式调用示例
        sb.append(" is great!")
          .replace(6, 10, "Python"); // 将 "Java" 替换为 "Python"
        System.out.println("链式调用后: " + sb.toString()); // 输出: Hello Python is great!
    }
}

replaceAll()replaceFirst() (正则表达式替换)

当你需要基于 模式(正则表达式)进行替换时,应该使用这两个方法。

a) String.replaceAll(String regex, String replacement)

  • 功能: 使用给定的正则表达式 regex 匹配字符串中的所有子串,并将其替换为 replacement
  • 参数:
    • regex: 正则表达式。
    • replacement: 替换字符串。
  • 返回值: 一个新的 String 对象。
  • 注意: replacement 中包含特殊字符(如 ),它们会被视为反向引用。

示例代码:

Java replace替换时,为何有时未生效?-图3
(图片来源网络,侵删)
public class ReplaceAllExample {
    public static void main(String[] args) {
        String str = "Order 123 is complete, Order 456 is pending.";
        // 将所有 "Order" 后跟一个空格和数字的模式替换为 "Ticket"
        String newStr = str.replaceAll("Order \\d+", "Ticket");
        System.out.println("replaceAll 结果: " + newStr); // 输出: Ticket is complete, Ticket is pending.
        // 反向引用示例:将 "apple, orange, banana" 替换为 "orange, apple, banana"
        String fruits = "apple, orange, banana";
        String swapped = fruits.replaceAll("(\\w+), (\\w+)", "$2, $1");
        System.out.println("反向引用结果: " + swapped); // 输出: orange, apple, banana
        // 解释: $1 对应第一个捕获组 (\\w+) -> "apple"
        //       $2 对应第二个捕获组 (\\w+) -> "orange"
    }
}

b) String.replaceFirst(String regex, String replacement)

  • 功能: 与 replaceAll 类似,但它 只替换第一个匹配 的子串。
  • 参数: 与 replaceAll 相同。
  • 返回值: 一个新的 String 对象。

示例代码:

public class ReplaceFirstExample {
    public static void main(String[] args) {
        String str = "Order 123 is complete, Order 456 is pending.";
        // 只替换第一个匹配的 "Order 数字"
        String newStr = str.replaceFirst("Order \\d+", "Ticket");
        System.out.println("replaceFirst 结果: " + newStr); // 输出: Ticket is complete, Order 456 is pending.
    }
}

总结与对比

方法 所属类 功能 是否修改原对象 是否支持正则表达式 主要用途
replace(char, char) String 替换所有单个字符 简单的字符替换
replace(CharSequence, CharSequence) String 替换所有子字符串 最常用,精确的子串替换
replace(int, int, String) StringBuilder 替换指定索引范围的内容 高效地、可变地修改字符串的一部分
replaceAll(String, String) String 替换所有匹配正则表达式的子串 基于复杂模式(如数字、空格)的替换
replaceFirst(String, String) String 替换第一个匹配正则表达式的子串 只替换第一个匹配项

如何选择?

  1. 简单替换一个或多个字符/固定子串?

    • 使用 String.replace(CharSequence target, CharSequence replacement),这是最安全、最通用的选择。
  2. 需要基于模式(如“所有数字”、“所有空格”)进行替换?

    • 使用 String.replaceAll(String regex, String replacement),如果只想替换第一个匹配项,用 replaceFirst
  3. 在一个循环中需要进行大量的字符串拼接和修改,追求高性能?

    • 使用 StringBuilderStringBuffer,并调用它们的 replace(int, int, String) 方法,这样可以避免创建大量中间字符串对象,减少内存开销和垃圾回收的压力。

String 的不可变性是 Java 设计中的一个核心原则,它在多线程环境下提供了天然的安全性,而 StringBuilder 则是为了解决 String 在频繁修改时性能问题而设计的。

分享:
扫描分享到社交APP
上一篇
下一篇