stringbuilder 更快是因为 string 不可变,每次+拼接都新建对象并触发 gc;而 stringbuilder 可变、复用内部数组,预分配容量可避免频繁扩容。

直接用 + 拼接字符串在循环中构建大量 HTML 或 SQL 时,会因频繁创建新字符串对象而严重拖慢性能;用 StringBuilder 预分配容量、复用内部字符数组,能显著减少内存分配和复制开销。
为什么 StringBuilder 更快?
Java 中 String 是不可变的。每次 + 拼接都会生成新对象,循环 1000 次就可能产生上千个临时字符串,触发多次 GC。StringBuilder 是可变的,内部维护一个 char[] 数组,扩容策略是“当前不够时翻倍+2”,避免频繁重分配。若提前知道大致长度(比如每条记录生成约 200 字符的 HTML),调用构造函数指定初始容量,效果更佳。
拼接动态 HTML 的实用写法
例如生成用户列表的 <ul><li>...</li></ul>:
// 假设 users 不为空,预估总长:ul 标签约 20 字 + 每个 li 约 150 字 × 用户数StringBuilder html = new StringBuilder(20 + users.size() * 150);html.append("<ul>");</ul>for (User u : users) { html.append("<li>")</li> .append(escapeHtml(u.getName())) .append(" — ") .append(escapeHtml(u.getEmail())) .append("");}html.append("");return html.toString();
拼接动态 SQL 要注意安全与结构
SQL 拼接必须防范注入,StringBuilder 只负责拼结构,参数值必须用 PreparedStatement 绑定——不要把用户输入直接 append 进去。
- 只用
StringBuilder拼接固定部分:表名、字段名、WHERE条件框架、ORDER BY等 - 动态列或条件数量不确定时,用
StringJoiner或手动控制逗号分隔(如if (first) first = false; else sb.append(", ");) - 示例:构建多条件查询的
WHERE子句
StringBuilder sql = new StringBuilder("SELECT * FROM user WHERE 1=1");if (status != null) { sql.append(" AND status = ?"); // 占位符,后续 setXXX}if (nameLike != null) { sql.append(" AND name LIKE ?");}// 执行时用 PreparedStatement 设置参数,不拼具体值
常见误区提醒
- 不要在循环外反复新建
StringBuilder:如果方法被高频调用,考虑复用(如 ThreadLocal 或池化),但多数场景直接 new 更清晰安全 - 避免链式调用过深导致可读性下降,适当拆行或提取局部变量
- 别用
StringBuilder替代模板引擎(如 Thymeleaf、MyBatis XML)——复杂 HTML/SQL 应交给专业工具,StringBuilder 适合简单、可控、性能敏感的场景
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











