StringBuilder
是 Java 中用于高效处理字符串拼接的核心类。它在需要频繁修改字符串内容的场景下,性能远超 String
和 StringBuffer
。
一、核心概念
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)
:删除从start
到end-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);
四、注意事项
- 线程安全:
StringBuilder
不是线程安全的。在多线程环境下应使用StringBuffer
或同步机制。 - 容量管理:自动扩容有性能开销。若能预估字符串长度,建议指定初始容量。
- 不可变性:
toString()
返回的String
是不可变的,后续修改StringBuilder
不影响已生成的String
。 - 方法链:
append
、insert
等方法返回this
,支持链式调用,但注意可读性。 - 空值处理:
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. 结合 StringWriter
和 PrintWriter
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.println("Hello");
pw.println("World");
String result = sw.toString(); // 底层使用 StringBuilder
总结
StringBuilder
是 Java 字符串处理的利器。掌握其核心概念、操作步骤和最佳实践,能显著提升代码性能和可维护性。关键点:
- 使用场景:频繁修改字符串内容。
- 核心优势:可变、高效、功能丰富。
- 性能要点:预设容量、避免线程共享、合理使用链式调用。
- 最终输出:别忘了
toString()
。
通过本指南,你已具备快速上手并高效使用 StringBuilder
的能力。在实际项目中多加练习,将成为你处理字符串的得力助手。