源本科技 | 码上会

Java 中的 StringBuffer 类

2025/12/26
34
0

学习目标

  • 理解 StringBuffer 的可变性与线程安全特性

  • 掌握 StringBuffer 的核心方法(appendinsertreplacedeletereverse 等)

  • 能够根据场景选择 StringStringBufferStringBuilder

  • 了解容量管理机制及其对性能的影响


什么是 StringBuffer

StringBuffer 是 Java 中用于表示可变字符序列的类。与不可变的 String 不同,StringBuffer 允许在不创建新对象的情况下直接修改内容。

关键特性

  • 可变:内容可被修改

  • 线程安全:所有方法均为 synchronized

  • 高效拼接:适合频繁字符串操作的场景

public class CoderHub {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer();
        sb.append("Hello");
        sb.append(" ");
        sb.append("world");
        
        String result = sb.toString();
        System.out.println(result); // Hello world
    }
}

💡 注意:最终通常调用 toString() 转为不可变 String 使用。


StringBuffer 构造方法

构造器

说明

StringBuffer()

创建空缓冲区,默认容量 16

StringBuffer(int capacity)

指定初始容量

StringBuffer(String str)

以指定字符串初始化,容量 = str.length() + 16

// 1. 默认构造(容量16)
StringBuffer sb1 = new StringBuffer();
sb1.append("Hello");

// 2. 指定容量(避免频繁扩容)
StringBuffer sb2 = new StringBuffer(50);
sb2.append("Java Programming");

// 3. 从字符串初始化
StringBuffer sb3 = new StringBuffer("Welcome");
sb3.append(" to Java");

System.out.println(sb1); // Hello
System.out.println(sb2); // Java Programming
System.out.println(sb3); // Welcome to Java

核心方法

1. append(String str)

在末尾追加内容。

StringBuffer sb = new StringBuffer("Hello ");
sb.append("Java");
System.out.println(sb); // Hello Java

支持多种类型:charintbooleanObject 等。


2. insert(int offset, String str)

在指定位置插入内容。

StringBuffer sb = new StringBuffer("Hello ");
sb.insert(1, "Java"); // 在索引1处插入
System.out.println(sb); // HJavaello 

索引越界会抛出 StringIndexOutOfBoundsException


3. replace(int start, int end, String str)

替换 [start, end) 区间的字符。

StringBuffer sb = new StringBuffer("Hello");
sb.replace(1, 3, "Java"); // 替换索引1~2("el" → "Java")
System.out.println(sb); // HJavalo

4. delete(int start, int end)

删除 [start, end) 区间的字符。

StringBuffer sb = new StringBuffer("Hello");
sb.delete(1, 3); // 删除 "el"
System.out.println(sb); // Hlo

还有 deleteCharAt(int index) 删除单个字符。


5. reverse()

反转整个字符序列。

StringBuffer sb = new StringBuffer("Hello");
sb.reverse();
System.out.println(sb); // olleH

常用于回文判断、字符串翻转等算法题。


6. capacity() 与扩容机制

  • 初始容量:16

  • 扩容公式:新容量 = (旧容量 × 2) + 2

StringBuffer sb = new StringBuffer();
System.out.println(sb.capacity()); // 16

sb.append("Hello"); // 长度5 < 16,容量不变
System.out.println(sb.capacity()); // 16

sb.append(" java is my favourite language"); // 总长 > 16
System.out.println(sb.capacity()); // 34 = (16*2)+2

优化建议:若预知数据量较大,使用 new StringBuffer(estimatedSize) 避免多次扩容。


7. length()

返回当前字符数量(非容量)。

StringBuffer sb = new StringBuffer("GeeksforGeeks");
System.out.println("Length = " + sb.length()); // 13

length()capacity()


其他重要方法

方法

功能

charAt(int index)

获取指定位置字符

setCharAt(int index, char ch)

修改指定位置字符

indexOf(String str) / lastIndexOf(String str)

查找子串位置

substring(int start) / substring(int start, int end)

截取子串(返回 String

toString()

转为不可变 String

ensureCapacity(int min)

确保容量至少为 min

trimToSize()

将容量缩减至当前长度(节省内存)


StringBuffer vs String vs StringBuilder

特性

String

StringBuffer

StringBuilder

可变性

❌ 不可变

✅ 可变

✅ 可变

线程安全

✅(因不可变)

✅(方法同步)

性能

拼接慢(产生大量中间对象)

中等(同步开销)

⚡ 快(无同步)

适用场景

少量操作、常量

多线程环境下的频繁修改

单线程下的频繁修改

选择指南

  • 单线程 + 高频修改 → StringBuilder

  • 多线程 + 高频修改 → StringBuffer

  • 内容固定 → String


重点总结

  • StringBuffer线程安全的可变字符序列

  • 所有修改操作(appendinsert 等)直接改变原对象

  • 默认容量 16,超限时按 (old×2)+2 扩容

  • 性能低于 StringBuilder,仅在多线程场景推荐使用

  • 最终通过 toString() 转为标准 String 对象

💡 最佳实践:在已知字符串操作次数和大致长度时,预先设置容量可显著减少内存拷贝,提升性能。


思考题

  1. 为什么 StringBuffer 的扩容公式是 (oldCapacity * 2) + 2?这种设计相比简单翻倍(*2)有什么优势?

  2. 在单线程环境中使用 StringBuffer 会导致什么性能问题?如何通过代码验证其比 StringBuilder 慢?

  3. 编写一个方法,使用 StringBuffer 实现“将句子中每个单词首字母大写”的功能(如 "hello world""Hello World")。