StringBuilder与StringBuffer
StringBuilder和StringBuffer是可变字符串序列。
概述对比
StringBuilder与StringBuffer区别
| 特性 | StringBuilder | StringBuffer |
|---|---|---|
| 线程安全 | 非安全 | 安全(synchronized) |
| 性能 | 高 | 较低(同步开销) |
| 出现版本 | Java 5 | Java 1.0 |
| 适用场景 | 单线程 | 多线程 |
选择原则
- 单线程环境:优先StringBuilder
- 多线程共享:必须StringBuffer
- 绝大多数场景:StringBuilder(性能好)
StringBuilder
创建StringBuilder
Java
// 默认构造(容量16)
StringBuilder sb1 = new StringBuilder();
// 指定容量
StringBuilder sb2 = new StringBuilder(100);
// 指定初始内容
StringBuilder sb3 = new StringBuilder("Hello");
append追加内容
Java
StringBuilder sb = new StringBuilder();
// 追加字符串
sb.append("Hello");
sb.append(" World");
// 追加其他类型
sb.append(123); // 追加数字
sb.append(true); // 追加boolean
sb.append(3.14); // 追加double
sb.append('\n'); // 追加字符
// 链式调用
StringBuilder sb2 = new StringBuilder()
.append("Hello")
.append(" ")
.append("World")
.append(123);
insert插入内容
Java
StringBuilder sb = new StringBuilder("Hello World");
// 在指定位置插入
sb.insert(5, ","); // "Hello, World"(索引5插入逗号)
sb.insert(0, "Say: "); // "Say: Hello, World"
// 插入其他类型
sb.insert(6, 123); // 插入数字
delete删除内容
Java
StringBuilder sb = new StringBuilder("Hello World");
// 删除指定范围
sb.delete(5, 6); // "HelloWorld"(删除索引5-6)
// 删除单个字符
sb.deleteCharAt(5); // "Helloorld"
// 清空
sb.delete(0, sb.length()); // 清空全部
replace替换内容
Java
StringBuilder sb = new StringBuilder("Hello World");
// 替换指定范围
sb.replace(6, 11, "Java"); // "Hello Java"(索引6-11替换为Java)
reverse反转字符串
Java
StringBuilder sb = new StringBuilder("Hello");
sb.reverse(); // "olleH"
// 再次反转恢复
sb.reverse(); // "Hello"
substring截取
Java
StringBuilder sb = new StringBuilder("Hello World");
// 截取子串(返回String)
String sub1 = sb.substring(6); // "World"
String sub2 = sb.substring(0, 5); // "Hello"
// substring不影响StringBuilder内容
System.out.println(sb); // "Hello World"(未变)
其他方法
Java
StringBuilder sb = new StringBuilder("Hello");
// 获取长度
int len = sb.length(); // 5
// 获取容量
int cap = sb.capacity(); // 默认16+5=21
// 获取字符
char c = sb.charAt(0); // 'H'
// 设置字符
sb.setCharAt(0, 'J'); // "Jello"
// 设置长度(截断或扩展)
sb.setLength(3); // "Jel"
// toString转为String
String str = sb.toString(); // "Jel"
StringBuffer
StringBuffer用法
用法与StringBuilder完全相同,只是线程安全。
Java
// 创建
StringBuffer sb = new StringBuffer();
// append追加
sb.append("Hello");
sb.append(" World");
// insert插入
sb.insert(5, ",");
// delete删除
sb.delete(5, 6);
// reverse反转
sb.reverse();
// toString转换
String result = sb.toString();
线程安全机制
StringBuffer方法使用synchronized修饰。
Java
// StringBuffer源码示例
public synchronized StringBuffer append(String str) {
super.append(str);
return this;
}
public synchronized StringBuffer insert(int offset, String str) {
super.insert(offset, str);
return this;
}
多线程使用场景
Java
// 多线程共享StringBuffer
public class LogCollector {
private StringBuffer logBuffer = new StringBuffer();
// 多线程同时调用
public void addLog(String log) {
logBuffer.append(log).append("\n");
}
public String getLogs() {
return logBuffer.toString();
}
}
容量管理
容量概念
Java
StringBuilder sb = new StringBuilder();
// length:实际内容长度
// capacity:可容纳容量(缓冲区大小)
sb.append("Hello"); // length=5
System.out.println(sb.capacity()); // 16(默认容量)
sb.append("123456789012"); // length=17
System.out.println(sb.capacity()); // 34(扩容:旧容量*2+2)
扩容机制
Java
// 添加内容超过容量时自动扩容
// 新容量 = (旧容量 + 1) * 2
// 扩容开销:创建新数组、复制数据
// 预设合适容量可避免扩容
预设容量优化
Java
// 不知道容量时预估
StringBuilder sb = new StringBuilder(1000);
// 避免频繁扩容
for (int i = 0; i < 1000; i++) {
sb.append(i); // 容量足够,无需扩容
}
// 设置容量
sb.ensureCapacity(500); // 确保最小容量
性能对比
单线程性能
Java
// StringBuilder快(无同步)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
sb.append("a");
}
// 约10ms
// StringBuffer慢(同步开销)
StringBuffer sb2 = new StringBuffer();
for (int i = 0; i < 100000; i++) {
sb2.append("a");
}
// 约15ms
与String拼接对比
Java
// StringBuilder最快
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.append(i);
}
String result = sb.toString();
// 约1ms
// String +拼接最慢
String result2 = "";
for (int i = 0; i < 10000; i++) {
result2 = result2 + i;
}
// 约500ms(每次创建新对象)
使用场景
SQL构建
Java
StringBuilder sql = new StringBuilder();
sql.append("SELECT id, name FROM user");
if (condition != null) {
sql.append(" WHERE ").append(condition);
}
sql.append(" ORDER BY create_time DESC");
sql.append(" LIMIT ").append(limit);
String finalSql = sql.toString();
JSON构建
Java
StringBuilder json = new StringBuilder();
json.append("{");
json.append("\"name\":\"").append(name).append("\",");
json.append("\"age\":").append(age);
json.append("}");
String jsonString = json.toString();
日志拼接
Java
StringBuilder log = new StringBuilder();
log.append(timestamp).append(" ");
log.append(level).append(" ");
log.append(message);
logger.info(log.toString());
路径拼接
Java
StringBuilder path = new StringBuilder();
path.append(basePath);
if (!basePath.endsWith("/")) {
path.append("/");
}
path.append(filename);
String fullPath = path.toString();
最佳实践
预设容量
Java
// 预估内容长度,预设容量
StringBuilder sb = new StringBuilder(预估长度);
// 避免频繁扩容,提升性能
避免频繁toString
Java
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
// 不要每次循环toString
// String s = sb.toString(); // 低效
}
String result = sb.toString(); // 最后转换一次
链式调用
Java
// 链式调用简洁
StringBuilder sb = new StringBuilder()
.append("Hello")
.append(" ")
.append("World");
单线程用StringBuilder
Java
// 单线程:StringBuilder性能好
public String buildResult(List<String> items) {
StringBuilder sb = new StringBuilder();
for (String item : items) {
sb.append(item);
}
return sb.toString();
}
要点总结
- StringBuilder可变字符串序列,非线程安全
- StringBuffer可变字符串序列,线程安全(synchronized)
- 单线程用StringBuilder,多线程用StringBuffer
- append追加内容,insert插入,delete删除
- replace替换,reverse反转
- substring截取返回String(不影响原内容)
- length获取长度,capacity获取容量
- toString转换为String
- 预设容量避免扩容开销
- 容量超出自动扩容:新容量 = 旧容量*2+2
- 链式调用简洁高效
- 性能:StringBuilder > StringBuffer > String拼接
📝 发现内容有误?点击此处直接编辑