Java StringBuffer
和 StringBuilder
类详解
一、概述
StringBuffer
和 StringBuilder
是 Java 中用于处理可变字符串的类,位于 java.lang
包中。它们提供了动态修改字符串内容的能力,避免了 String
类的不可变性带来的性能开销。
- 可变性:与
String
不同,StringBuffer
和StringBuilder
的内容可以被修改。 - 底层实现:两者内部都使用字符数组(
char[]
)来存储字符串,当数组容量不足时会自动扩容。 - 适用场景:
StringBuffer
:线程安全,适合多线程环境。StringBuilder
:非线程安全,适合单线程环境,性能更高。
二、主要区别
特性 | StringBuffer | StringBuilder |
---|---|---|
线程安全 | 是(方法使用 synchronized 修饰) | 否(方法未使用 synchronized 修饰) |
性能 | 较低(线程安全开销) | 较高(无同步开销) |
适用场景 | 多线程环境下的字符串操作 | 单线程环境下的字符串操作 |
引入版本 | Java 1.0 | Java 5.0 |
三、常用方法
StringBuffer
和 StringBuilder
的 API 几乎完全相同,以下是常用方法的说明:
- 构造方法:
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");
- 追加内容:
append(String str)
:追加字符串。append(char c)
:追加字符。append(int i)
:追加整数。- 其他重载方法支持追加各种数据类型。
StringBuffer sb = new StringBuffer("Hello");
sb.append(" ").append("World").append("!"); // "Hello World!"
- 插入内容:
insert(int offset, String str)
:在指定位置插入字符串。insert(int offset, char c)
:在指定位置插入字符。
StringBuffer sb = new StringBuffer("Hello");
sb.insert(5, " Java"); // "Hello Java"
- 删除内容:
delete(int start, int end)
:删除从start
到end - 1
的字符。deleteCharAt(int index)
:删除指定位置的字符。
StringBuffer sb = new StringBuffer("Hello World");
sb.delete(5, 11); // "Hello"
sb.deleteCharAt(4); // "Hell"
- 替换内容:
replace(int start, int end, String str)
:替换指定范围的字符。
StringBuffer sb = new StringBuffer("Hello World");
sb.replace(6, 11, "Java"); // "Hello Java"
- 反转字符串:
reverse()
:反转字符串内容。
StringBuffer sb = new StringBuffer("Hello");
sb.reverse(); // "olleH"
- 获取子字符串:
substring(int start)
:从start
开始截取到末尾。substring(int start, int end)
:截取从start
到end - 1
的子字符串。
StringBuffer sb = new StringBuffer("Hello World");
String sub = sb.substring(6, 11); // "World"
- 获取长度和容量:
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
块)。
五、使用场景推荐
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,"
StringBuffer
:
- 多线程环境下的字符串操作。
- 需要线程安全的场景(如 Web 应用中的请求处理)。
- 示例:
class ThreadSafeExample { private static StringBuffer sb = new StringBuffer(); public static synchronized void addString(String str) { sb.append(str); } }
六、注意事项
- 容量扩展:
- 当字符串长度超过当前容量时,
StringBuffer
和StringBuilder
会自动扩容,默认扩容为原容量的 2 倍 + 2。 - 如果知道字符串的最终长度,可以预先分配足够的容量以避免频繁扩容:
java StringBuilder sb = new StringBuilder(1000); // 初始容量 1000
- 字符串不可变性:
StringBuffer
和StringBuilder
的toString()
方法返回的是新的String
对象,原对象不会被修改。
- 线程安全选择:
- 不要在单线程环境中使用
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,
通过以上内容,可以全面了解 StringBuffer
和 StringBuilder
的用法、区别和适用场景,从而在实际开发中做出合理的选择。