字符串拼接与性能
字符串拼接有多种方式,性能差异显著。
拼接方式
+运算符拼接
Java
String s1 = "Hello";
String s2 = "World";
// +运算符拼接
String result = s1 + " " + s2; // "Hello World"
// 多个字符串拼接
String result2 = "a" + "b" + "c"; // "abc"
concat方法拼接
Java
String s1 = "Hello";
String s2 = "World";
// concat拼接
String result = s1.concat(" ").concat(s2); // "Hello World"
// concat只接受一个参数
String result2 = s1.concat(s2); // "HelloWorld"
StringBuilder拼接
Java
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" ");
sb.append("World");
String result = sb.toString(); // "Hello World"
// 链式调用
String result2 = new StringBuilder()
.append("Hello")
.append(" ")
.append("World")
.toString();
String.join拼接(Java 8+)
Java
// 用分隔符拼接多个字符串
String result = String.join(",", "a", "b", "c"); // "a,b,c"
// 拼接数组
String[] arr = {"a", "b", "c"};
String result2 = String.join("-", arr); // "a-b-c"
+运算符性能
编译优化
+运算符在编译时可能优化。
Java
// 编译期常量:直接合并
String s1 = "a" + "b" + "c";
// 编译后:String s1 = "abc";
// 变量参与:编译器生成StringBuilder
String a = "a";
String b = "b";
String s2 = a + b;
// 编译后等价:
// new StringBuilder().append(a).append(b).toString()
循环拼接问题
循环中使用+会产生大量临时对象。
Java
// 低效:每次循环创建StringBuilder
String result = "";
for (int i = 0; i < 1000; i++) {
result = result + i;
// 每次循环:new StringBuilder().append(result).append(i).toString()
// 产生大量临时对象
}
// 高效:使用StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i); // 不创建新对象
}
String result = sb.toString();
StringBuilder详解
StringBuilder特性
- 可变字符串序列
- append方法追加内容
- 非线程安全(单线程使用)
- 性能优于StringBuffer
Java
StringBuilder sb = new StringBuilder();
// append追加
sb.append("Hello");
sb.append(" ");
sb.append("World");
// 插入
sb.insert(5, ","); // "Hello, World"
// 删除
sb.delete(5, 6); // "Hello World"
// 反转
sb.reverse(); // "dlroW olleH"
// 获取结果
String result = sb.toString();
容量管理
Java
// 默认容量16
StringBuilder sb1 = new StringBuilder();
// 指定初始容量(避免扩容)
StringBuilder sb2 = new StringBuilder(100);
// 指定初始内容
StringBuilder sb3 = new StringBuilder("Hello");
// 容量自动扩容(超出时翻倍)
sb.append大量内容时会自动扩容
预设容量优化
Java
// 不知道容量时,预估设置
StringBuilder sb = new StringBuilder(1000); // 避免频繁扩容
// 扩容开销:创建新数组、复制数据
// 预设合适容量可提升性能
StringBuffer详解
StringBuffer特性
- 可变字符串序列
- 线程安全(方法synchronized)
- 性能低于StringBuilder
- 多线程环境使用
Java
// StringBuffer用法与StringBuilder相同
StringBuffer sb = new StringBuffer();
sb.append("Hello");
sb.append(" World");
String result = sb.toString();
StringBuilder与StringBuffer对比
| 特性 | StringBuilder | StringBuffer |
|---|---|---|
| 线程安全 | 不安全 | 安全(synchronized) |
| 性能 | 高 | 低 |
| 使用场景 | 单线程 | 多线程 |
| 推荐使用 | 单线程首选 | 多线程必须 |
Java
// 单线程:StringBuilder
StringBuilder sb = new StringBuilder();
// 多线程共享:StringBuffer
StringBuffer sb = new StringBuffer();
拼接性能对比
性能测试示例
Java
// 方式1:+运算符循环(最慢)
String s1 = "";
for (int i = 0; i < 10000; i++) {
s1 = s1 + "a"; // 约500ms
}
// 方式2:StringBuilder(最快)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.append("a"); // 约1ms
}
// 方式3:concat方法(慢)
String s3 = "";
for (int i = 0; i < 10000; i++) {
s3 = s3.concat("a"); // 约300ms
}
性能排序
Java
性能从高到低:
StringBuilder > StringBuffer > +运算符(编译优化) > concat > +运算符(循环)
拼接场景选择
少量拼接用+
Java
// 2-3个字符串:+运算符简洁
String name = firstName + " " + lastName;
// 常量拼接:编译优化
String path = "/api" + "/user" + "/list"; // 编译为"/api/user/list"
大量拼接用StringBuilder
Java
// 循环拼接:StringBuilder
StringBuilder sb = new StringBuilder();
for (String item : items) {
sb.append(item).append(",");
}
String result = sb.toString();
// 动态构建:StringBuilder
StringBuilder sql = new StringBuilder();
sql.append("SELECT * FROM user");
if (condition != null) {
sql.append(" WHERE ").append(condition);
}
sql.append(" ORDER BY id");
多线程用StringBuffer
Java
// 多线程共享对象
StringBuffer sb = new StringBuffer();
// 多个线程同时append
sb.append(data);
分隔符拼接用join
Java
// 有分隔符:String.join简洁
String ids = String.join(",", idList);
// CSV格式
String csv = String.join("\n", lines);
常见误区
误区1:+比StringBuilder快
Java
// 单次拼接+优化后性能接近
String s = a + b; // 编译优化为StringBuilder
// 循环拼接+慢很多
for (...) {
s = s + x; // 每次循环创建StringBuilder
}
误区2:StringBuilder必须预设容量
Java
// 不预设也能用,只是可能扩容
StringBuilder sb = new StringBuilder(); // 默认16
sb.append("很长的内容..."); // 自动扩容
// 预设容量只是优化,不是必须
误区3:concat比+快
text
// concat每次创建新String,比+慢
String s = "a".concat("b"); // 新对象
// +编译优化后更快
String s = "a" + "b"; // 编译期合并
要点总结
- +运算符:简洁,编译优化,适合少量拼接
- concat方法:每次创建新对象,性能较低
- StringBuilder:可变序列,高性能,单线程首选
- StringBuffer:线程安全,多线程使用
- String.join:分隔符拼接,简洁易用
- 循环拼接必须用StringBuilder
- +运算符循环拼接产生大量临时对象
- 预设StringBuilder容量避免扩容开销
- 单线程用StringBuilder,多线程用StringBuffer
- 大量拼接性能:StringBuilder >> +(循环)
📝 发现内容有误?点击此处直接编辑