1. 概述

本文将深入探讨 Java 中 StringBuilderStringBuffer 的核心异同点。简单来说,StringBuilder 是 Java 1.5 引入的 StringBuffer 替代品,两者在设计理念上存在关键差异。

2. 相似之处

StringBuilderStringBuffer 都创建可变字符序列对象。我们通过对比不可变的 String 类来理解其工作原理:

String immutable = "abc";
immutable = immutable + "def";  // ❌ 实际创建了新对象

看似修改了原对象,实则因 String 的不可变性,每次操作都会生成新实例。而使用 StringBufferStringBuilder 时:

StringBuffer sb = new StringBuffer("abc");
sb.append("def");  // ✅ 直接修改原对象内容

通过调用 append() 方法直接修改原对象,无需创建新实例,体现了两者的可变性

3. 核心差异

StringBuffer 是同步的线程安全实现,而 StringBuilder 兼容其 API 但不保证同步。由于缺少同步开销,StringBuilder 性能更优,适用于单线程场景。

3.1 性能对比

在小规模迭代中差异可忽略,但通过 JMH 微基准测试(1k 次迭代):

@State(Scope.Benchmark)
public static class MyState {
    int iterations = 1000;
    String initial = "abc";
    String suffix = "def";
}

@Benchmark
public StringBuffer benchmarkStringBuffer(MyState state) {
    StringBuffer stringBuffer = new StringBuffer(state.initial);
    for (int i = 0; i < state.iterations; i++) {
        stringBuffer.append(state.suffix);
    }
    return stringBuffer;
}

@Benchmark
public StringBuilder benchmarkStringBuilder(MyState state) {
    StringBuilder stringBuilder = new StringBuilder(state.initial);
    for (int i = 0; i < state.iterations; i++) {
        stringBuilder.append(state.suffix);
    }
    return stringBuilder;
}

测试结果(吞吐量模式,分数越高越好):

Benchmark                                          Mode  Cnt      Score      Error  Units
StringBufferStringBuilder.benchmarkStringBuffer   thrpt  200  86169.834 ±  972.477  ops/s
StringBufferStringBuilder.benchmarkStringBuilder  thrpt  200  91076.952 ± 2818.028  ops/s

当迭代增至 1M 次时差异更明显:

Benchmark                                          Mode  Cnt   Score   Error  Units
StringBufferStringBuilder.benchmarkStringBuffer   thrpt  200  77.178 ± 0.898  ops/s
StringBufferStringBuilder.benchmarkStringBuilder  thrpt  200  85.769 ± 1.966  ops/s

⚠️ 注意:微基准测试结果需谨慎解读,实际应用性能需结合具体场景分析。

4. 实践建议

StringBuffer 因线程安全设计性能较低,StringBuilder 在单线程场景更高效。但需注意:

  • ✅ 单线程环境优先使用 StringBuilder
  • ✅ 多线程共享数据时必须用 StringBuffer
  • ⚠️ 性能提升可能微小,替换前建议做实际性能分析
  • ❌ 避免在低频操作中过度优化

代码示例可在 GitHub 获取完整实现。