一、方法定义

public void trimToSize()

参数:

  • 无参数

返回值:

  • void(无返回值)

二、功能说明

trimToSize() 方法用于StringBuilder 的内部缓冲区容量(capacity)调整为当前字符序列的实际长度(length),以节省内存空间。

核心功能:

  • 减少内存占用:释放未使用的缓冲区空间
  • 优化存储:使容量等于当前字符串长度
  • 不可逆操作:调用后若再追加内容,可能触发扩容

ensureCapacity() 的关系:

  • ensureCapacity(int minimumCapacity)确保容量至少为指定值(可能扩容)
  • trimToSize()缩小容量至实际长度(只可能缩容)

三、示例代码

1. 基本使用

StringBuilder sb = new StringBuilder(100); // 初始容量100
sb.append("Hello");

System.out.println("Length: " + sb.length());     // 输出: 5
System.out.println("Capacity: " + sb.capacity()); // 输出: 100

sb.trimToSize();

System.out.println("After trimToSize:");
System.out.println("Length: " + sb.length());     // 输出: 5
System.out.println("Capacity: " + sb.capacity()); // 输出: 5

2. 验证内存优化效果

StringBuilder sb = new StringBuilder();
sb.append("A".repeat(1000)); // 添加1000个字符

System.out.println("初始 - 长度: " + sb.length() + ", 容量: " + sb.capacity());
// 示例输出: 初始 - 长度: 1000, 容量: 1024

sb.setLength(10); // 将内容截短到10个字符
System.out.println("截短后 - 长度: " + sb.length() + ", 容量: " + sb.capacity());
// 输出: 截短后 - 长度: 10, 容量: 1024 (内存仍被占用)

sb.trimToSize();
System.out.println("trimToSize后 - 长度: " + sb.length() + ", 容量: " + sb.capacity());
// 输出: trimToSize后 - 长度: 10, 容量: 10 (内存已释放)

3. 链式调用限制

StringBuilder sb = new StringBuilder("Test");
// sb.trimToSize().append("More"); // ❌ 编译错误!trimToSize() 返回 void

// 正确做法:分步调用
sb.trimToSize();
sb.append("More");

四、使用技巧

1. 在构建完成后调用

当确定不再追加内容时,调用 trimToSize() 优化内存。

StringBuilder sb = new StringBuilder();
// ... 构建字符串
sb.append("Final content");

// 构建完成,优化内存
sb.trimToSize();

// 后续只读操作或转换为String
String result = sb.toString();

2. toString() 配合使用

虽然 toString() 会创建新字符串,但调用 trimToSize() 可减少 StringBuilder 自身的内存占用。

StringBuilder sb = new LargeStringBuilder();
// ... 处理
sb.trimToSize(); // 优化StringBuilder自身内存
String result = sb.toString(); // 创建String对象

3. 监控内存使用

可用于调试和性能分析。

System.out.println("Before: len=" + sb.length() + ", cap=" + sb.capacity());
sb.trimToSize();
System.out.println("After: len=" + sb.length() + ", cap=" + sb.capacity());

五、常见错误

1. 误以为返回 StringBuilder

// ❌ 错误:尝试链式调用
// StringBuilder result = sb.trimToSize().append("text"); // 编译错误

// ✅ 正确:分步调用
sb.trimToSize();
sb.append("text");

2. 在频繁修改前调用

StringBuilder sb = new StringBuilder();
sb.trimToSize(); // 此时容量=0
sb.append("Hello"); // 触发扩容
sb.append(" World"); // 可能再次扩容
// 失去了 StringBuilder 预分配容量的优势

3. 期望释放 String 内存

trimToSize() 只优化 StringBuilder 自身的缓冲区,不影响通过 toString() 创建的 String 对象。


六、注意事项

  1. 无返回值trimToSize() 返回 void,不支持链式调用。
  2. 仅缩容:只能减少容量,不能增加。
  3. 性能权衡
    • 优点:节省内存
    • 缺点:后续追加内容可能触发数组复制(扩容)
  4. 线程不安全:与其他 StringBuilder 方法一样,非线程安全。
  5. JVM 优化:现代 JVM 内存管理高效,小幅度缩容可能意义不大。
  6. 实际长度:基于 length() 调整容量,而非字符内容大小。

七、最佳实践与性能优化

✅ 最佳实践

场景 推荐做法
构建完成后的优化 在确定不再修改后调用 trimToSize()
内存敏感应用 对大型 StringBuilder 调用以减少内存占用
工具类/库开发 提供选项是否调用 trimToSize()
高频操作 避免频繁调用,通常不需要

⚠️ 性能建议

  • 一般应用:通常不需要显式调用 trimToSize(),JVM 和 StringBuilder 的默认扩容策略已足够高效。
  • 内存敏感场景:如处理大量文本、Android 应用、嵌入式系统,可在构建完成后调用。
  • 避免过度优化:微小的内存节省可能带来后续扩容的性能开销。

示例:何时调用

// ✅ 推荐:构建完成,长期持有
StringBuilder config = new StringBuilder();
// 构建配置字符串
config.trimToSize(); // 优化内存,长期使用

// ⚠️ 不推荐:频繁修改
StringBuilder log = new StringBuilder();
while (hasMoreLogs()) {
    log.trimToSize(); // ❌ 每次都缩容,后续append会扩容,性能更差
    log.append(nextLog());
}

八、总结

StringBuilder.trimToSize() 是一个内存优化工具,用于将内部缓冲区缩减到实际需要的大小。

核心要点:

项目 说明
功能 缩小容量至当前长度
返回值 void,不支持链式调用
主要用途 节省内存空间
调用时机 构建完成且不再修改时
性能影响 节省内存,但可能增加后续扩容开销
必要性 一般应用中非必需

使用口诀:

trimToSize缩容量,内存优化有一套;
返回void莫链式,构建完成才需要;
频繁修改别乱用,扩容代价要知道;
一般情况可不用,省心省力最重要。

在绝大多数情况下,可以安全地忽略 trimToSize()。只有在处理超大字符串或内存极度敏感的场景下,才需要考虑使用它来优化内存占用。