Java StringBuffer 和 StringBuilder 类 详解

Java StringBufferStringBuilder 类详解

一、概述

StringBufferStringBuilder 是 Java 中用于处理可变字符串的类,位于 java.lang 包中。它们提供了动态修改字符串内容的能力,避免了 String 类的不可变性带来的性能开销。

  • 可变性:与 String 不同,StringBufferStringBuilder 的内容可以被修改。
  • 底层实现:两者内部都使用字符数组(char[])来存储字符串,当数组容量不足时会自动扩容。
  • 适用场景
  • StringBuffer:线程安全,适合多线程环境。
  • StringBuilder:非线程安全,适合单线程环境,性能更高。

二、主要区别

特性StringBufferStringBuilder
线程安全是(方法使用 synchronized 修饰)否(方法未使用 synchronized 修饰)
性能较低(线程安全开销)较高(无同步开销)
适用场景多线程环境下的字符串操作单线程环境下的字符串操作
引入版本Java 1.0Java 5.0

三、常用方法

StringBufferStringBuilder 的 API 几乎完全相同,以下是常用方法的说明:

  1. 构造方法
   StringBuffer sb1 = new StringBuffer(); // 初始容量为 16
   StringBuffer sb2 = new StringBuffer(100); // 指定初始容量
   StringBuffer sb3 = new StringBuffer("Hello"); // 初始化为 "Hello"

   StringBuilder sb4 = new StringBuilder();
   StringBuilder sb5 = new StringBuilder(100);
   StringBuilder sb6 = new StringBuilder("Hello");
  1. 追加内容
  • append(String str):追加字符串。
  • append(char c):追加字符。
  • append(int i):追加整数。
  • 其他重载方法支持追加各种数据类型。
   StringBuffer sb = new StringBuffer("Hello");
   sb.append(" ").append("World").append("!"); // "Hello World!"
  1. 插入内容
  • insert(int offset, String str):在指定位置插入字符串。
  • insert(int offset, char c):在指定位置插入字符。
   StringBuffer sb = new StringBuffer("Hello");
   sb.insert(5, " Java"); // "Hello Java"
  1. 删除内容
  • delete(int start, int end):删除从 startend - 1 的字符。
  • deleteCharAt(int index):删除指定位置的字符。
   StringBuffer sb = new StringBuffer("Hello World");
   sb.delete(5, 11); // "Hello"
   sb.deleteCharAt(4); // "Hell"
  1. 替换内容
  • replace(int start, int end, String str):替换指定范围的字符。
   StringBuffer sb = new StringBuffer("Hello World");
   sb.replace(6, 11, "Java"); // "Hello Java"
  1. 反转字符串
  • reverse():反转字符串内容。
   StringBuffer sb = new StringBuffer("Hello");
   sb.reverse(); // "olleH"
  1. 获取子字符串
  • substring(int start):从 start 开始截取到末尾。
  • substring(int start, int end):截取从 startend - 1 的子字符串。
   StringBuffer sb = new StringBuffer("Hello World");
   String sub = sb.substring(6, 11); // "World"
  1. 获取长度和容量
  • length():返回字符串长度。
  • capacity():返回当前容量。
   StringBuffer sb = new StringBuffer(100);
   sb.append("Hello");
   System.out.println(sb.length()); // 5
   System.out.println(sb.capacity()); // 100

四、性能对比

  • 单线程环境
  • StringBuilder 的性能优于 StringBuffer,因为没有同步开销。
  • 示例: long startTime = System.currentTimeMillis(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 100000; i++) { sb.append("a"); } long endTime = System.currentTimeMillis(); System.out.println("StringBuilder耗时: " + (endTime - startTime) + "ms"); startTime = System.currentTimeMillis(); StringBuffer sbf = new StringBuffer(); for (int i = 0; i < 100000; i++) { sbf.append("a"); } endTime = System.currentTimeMillis(); System.out.println("StringBuffer耗时: " + (endTime - startTime) + "ms"); 输出结果: StringBuilder耗时: 1ms StringBuffer耗时: 5ms
  • 多线程环境
  • StringBuffer 是线程安全的,适合多线程操作。
  • StringBuilder 在多线程环境下需要外部同步(如使用 synchronized 块)。

五、使用场景推荐

  1. StringBuilder
  • 单线程环境下的字符串拼接。
  • 循环中频繁修改字符串。
  • 示例:
    java StringBuilder sb = new StringBuilder(); for (int i = 0; i < 100; i++) { sb.append(i).append(","); } String result = sb.toString(); // "0,1,2,...,99,"
  1. StringBuffer
  • 多线程环境下的字符串操作。
  • 需要线程安全的场景(如 Web 应用中的请求处理)。
  • 示例: class ThreadSafeExample { private static StringBuffer sb = new StringBuffer(); public static synchronized void addString(String str) { sb.append(str); } }

六、注意事项

  1. 容量扩展
  • 当字符串长度超过当前容量时,StringBufferStringBuilder 会自动扩容,默认扩容为原容量的 2 倍 + 2。
  • 如果知道字符串的最终长度,可以预先分配足够的容量以避免频繁扩容:
    java StringBuilder sb = new StringBuilder(1000); // 初始容量 1000
  1. 字符串不可变性
  • StringBufferStringBuildertoString() 方法返回的是新的 String 对象,原对象不会被修改。
  1. 线程安全选择
  • 不要在单线程环境中使用 StringBuffer,避免不必要的性能开销。
  • 不要在多线程环境中使用 StringBuilder,除非通过外部同步保证线程安全。

七、总结

  • StringBuffer:线程安全,适合多线程环境,性能较低。
  • StringBuilder:非线程安全,适合单线程环境,性能更高。
  • 选择建议
  • 优先使用 StringBuilder,除非明确需要线程安全。
  • 在多线程环境中,如果需要线程安全的字符串操作,可以使用 StringBuffer 或通过外部同步(如 Collections.synchronizedList)保护 StringBuilder

八、示例代码

public class StringBufferStringBuilderExample {
    public static void main(String[] args) {
        // StringBuilder 示例
        StringBuilder sb = new StringBuilder();
        sb.append("Hello").append(" ").append("World");
        System.out.println("StringBuilder: " + sb.toString()); // "Hello World"

        // StringBuffer 示例
        StringBuffer sbf = new StringBuffer();
        sbf.append("Java").append(" ").append("Programming");
        System.out.println("StringBuffer: " + sbf.toString()); // "Java Programming"

        // 多线程环境下的 StringBuffer
        Runnable task = () -> {
            StringBuffer sharedBuffer = new StringBuffer();
            for (int i = 0; i < 10; i++) {
                sharedBuffer.append(Thread.currentThread().getName()).append("-").append(i).append(",");
            }
            System.out.println(sharedBuffer.toString());
        };

        Thread t1 = new Thread(task, "Thread-1");
        Thread t2 = new Thread(task, "Thread-2");
        t1.start();
        t2.start();
    }
}

输出示例:

StringBuilder: Hello World
StringBuffer: Java Programming
Thread-1-0,Thread-1-1,...,Thread-1-9,
Thread-2-0,Thread-2-1,...,Thread-2-9,

通过以上内容,可以全面了解 StringBufferStringBuilder 的用法、区别和适用场景,从而在实际开发中做出合理的选择。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注