StringBuilder 是 Java 中用于高效处理字符串拼接的核心类。它在需要频繁修改字符串内容的场景下,性能远超 StringStringBuffer

一、核心概念

1. 什么是 StringBuilder

  • StringBuilder 是 Java 提供的一个可变字符序列类,位于 java.lang 包中。
  • 与不可变的 String 类不同,StringBuilder 对象的内容可以在创建后被修改,而无需创建新的对象。
  • 它不是线程安全的,因此在单线程环境下性能优于 StringBuffer

2. 为什么使用 StringBuilder

  • 性能优势:频繁拼接字符串时,使用 + 操作符会不断创建新的 String 对象,导致内存浪费和频繁的垃圾回收。StringBuilder 通过内部的字符数组动态扩容,避免了这个问题。
  • 灵活性:支持插入、删除、替换、反转等操作,功能比 String 更强大。
  • 适用场景:日志构建、SQL 语句生成、字符串格式化、循环中拼接等。

3. 内部结构

  • StringBuilder 内部维护一个可变长度的字符数组(char[])。
  • 初始容量默认为 16 个字符,当内容超过当前容量时,会自动扩容(通常是当前容量的 2 倍 + 2)。
  • 所有修改操作都在原对象上进行,不产生新对象。

二、操作步骤(非常详细)

步骤 1:导入类

// StringBuilder 在 java.lang 包中,无需显式导入
// 但为了清晰,可写:
import java.lang.StringBuilder;

步骤 2:创建 StringBuilder 实例

方法 1:无参构造函数(推荐初学者)

StringBuilder sb = new StringBuilder();
// 初始容量为 16

方法 2:指定初始容量

StringBuilder sb = new StringBuilder(50);
// 初始容量为 50,适合预估字符串长度的场景

方法 3:基于字符串初始化

StringBuilder sb = new StringBuilder("Hello");
// 初始内容为 "Hello",容量为 16 + 字符串长度

步骤 3:添加内容(追加)

使用 append() 方法

sb.append("World");        // 添加字符串
sb.append(123);            // 添加整数
sb.append(true);           // 添加布尔值
sb.append('A');            // 添加字符
sb.append(3.14);           // 添加浮点数
sb.append(sb2);            // 添加另一个 StringBuilder

append() 方法返回 StringBuilder 自身,支持链式调用。

链式调用示例

StringBuilder sb = new StringBuilder();
sb.append("Name: ").append("Alice").append(", Age: ").append(25);
// 结果:Name: Alice, Age: 25

步骤 4:插入内容(指定位置插入)

使用 insert() 方法

StringBuilder sb = new StringBuilder("HelloWorld");
sb.insert(5, " "); // 在索引 5 处插入空格
// 结果:Hello World

参数:insert(int offset, Object obj)offset 从 0 开始。

插入不同类型

sb.insert(0, "Start: ");   // 插入字符串
sb.insert(6, 100);         // 插入整数

步骤 5:删除内容

使用 delete() 方法

StringBuilder sb = new StringBuilder("Hello World");
sb.delete(5, 6); // 删除索引 5 到 6(不包含 6)的字符
// 结果:HelloWorld

delete(int start, int end):删除从 startend-1 的字符。

删除单个字符

sb.deleteCharAt(5); // 删除索引 5 处的字符

步骤 6:替换内容

使用 replace() 方法

StringBuilder sb = new StringBuilder("Hello World");
sb.replace(6, 11, "Java"); // 将索引 6 到 11 替换为 "Java"
// 结果:Hello Java

replace(int start, int end, String str):替换指定范围的字符。

步骤 7:反转字符串

使用 reverse() 方法

StringBuilder sb = new StringBuilder("Hello");
sb.reverse();
// 结果:olleH

步骤 8:获取字符串结果

使用 toString() 方法

String result = sb.toString();
// 将 StringBuilder 转换为不可变的 String

注意:toString() 返回的是新 String 对象,原 StringBuilder 仍可继续修改。

步骤 9:查询信息

获取长度和容量

int length = sb.length();     // 当前字符数
int capacity = sb.capacity(); // 当前数组容量

获取指定位置字符

char ch = sb.charAt(0); // 获取索引 0 处的字符

设置指定位置字符

sb.setCharAt(0, 'h'); // 将索引 0 处的字符改为 'h'

三、常见错误

错误 1:忘记调用 toString()

StringBuilder sb = new StringBuilder("Hello");
System.out.println(sb); // 输出对象地址,不是内容!
// 正确做法:
System.out.println(sb.toString());

错误 2:索引越界

StringBuilder sb = new StringBuilder("Hi");
sb.delete(5, 6); // 抛出 StringIndexOutOfBoundsException
// 解决:检查 `length()`,确保索引有效。

错误 3:在多线程中共享 StringBuilder

// 错误:StringBuilder 非线程安全
StringBuilder sb = new StringBuilder();
// 多个线程同时调用 sb.append(...) 可能导致数据错乱
// 解决:使用 `StringBuffer` 或加锁

错误 4:过度扩容

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
    sb.append("a");
}
// 频繁扩容影响性能
// 解决:预设足够容量
StringBuilder sb2 = new StringBuilder(10000);

四、注意事项

  1. 线程安全StringBuilder 不是线程安全的。在多线程环境下应使用 StringBuffer 或同步机制。
  2. 容量管理:自动扩容有性能开销。若能预估字符串长度,建议指定初始容量。
  3. 不可变性toString() 返回的 String 是不可变的,后续修改 StringBuilder 不影响已生成的 String
  4. 方法链appendinsert 等方法返回 this,支持链式调用,但注意可读性。
  5. 空值处理append(null) 会添加字符串 "null",而非抛出异常。

五、使用技巧

技巧 1:预设容量提升性能

// 预估最终字符串长度约为 1000
StringBuilder sb = new StringBuilder(1000);

技巧 2:链式调用简化代码

StringBuilder sb = new StringBuilder()
    .append("User: ").append(username)
    .append(", Score: ").append(score);

技巧 3:利用 delete() 清空内容

sb.delete(0, sb.length()); // 清空 StringBuilder
// 比新建对象更高效

技巧 4:与 String.join() 配合

List<String> list = Arrays.asList("a", "b", "c");
StringBuilder sb = new StringBuilder();
sb.append(String.join("-", list)); // 快速拼接列表

六、最佳实践与性能优化

1. 何时使用 StringBuilder

  • 循环中拼接字符串(>2 次)
  • 构建动态 SQL、JSON、XML
  • 日志信息组装
  • 字符串格式化(比 String.format 更快)

2. 性能对比示例

// 方式1:使用 +(低效)
String s = "";
for (int i = 0; i < 1000; i++) {
    s += "a"; // 每次创建新 String
}

// 方式2:使用 StringBuilder(高效)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
    sb.append("a");
}
String result = sb.toString();

3. 避免频繁扩容

// 优化前:默认容量 16,可能扩容多次
StringBuilder sb = new StringBuilder();

// 优化后:预设容量
StringBuilder sb = new StringBuilder(expectedLength);

4. 合理选择类

  • 单线程大量拼接 → StringBuilder
  • 多线程共享拼接 → StringBuffer
  • 简单拼接(2-3 次)→ String +(编译器会优化为 StringBuilder)

5. 监控容量变化

System.out.println("Length: " + sb.length());
System.out.println("Capacity: " + sb.capacity());
// 调试时检查是否频繁扩容

6. 结合 StringWriterPrintWriter

StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.println("Hello");
pw.println("World");
String result = sw.toString(); // 底层使用 StringBuilder

总结

StringBuilder 是 Java 字符串处理的利器。掌握其核心概念、操作步骤和最佳实践,能显著提升代码性能和可维护性。关键点:

  • 使用场景:频繁修改字符串内容。
  • 核心优势:可变、高效、功能丰富。
  • 性能要点:预设容量、避免线程共享、合理使用链式调用。
  • 最终输出:别忘了 toString()

通过本指南,你已具备快速上手并高效使用 StringBuilder 的能力。在实际项目中多加练习,将成为你处理字符串的得力助手。