发布于2026-07-04 阅读(0)
扫一扫,手机访问
Ja va 字符串拼接的性能问题,其实没那么玄乎。说到底,决定性能的不是用了“+”号还是“concat”方法,而是代码在什么上下文里跑、每个语句执行了多少次。String 对象不可变,每次拼接都意味着新对象的诞生——这本身不是问题,问题在于“在循环里狂拼”,那才是灾难。
说实话,很多开发者一听到“字符串拼接”就说“别用+”,这个结论太绝对了。真正该警惕的场景,下面会逐一拆开来看。
你以为写了一句 s += "x",实际上 Ja va 编译器在背后干了三件事:先 new 一个 StringBuilder(默认容量 16),然后调用 append 把旧字符串和新内容拼上,最后 toString 生成新 String。旧字符串立马变成待回收的垃圾。循环 1 万次,就创建 1 万个 StringBuilder 和 1 万个中间 String——GC 不爆才怪,时间复杂度直接奔着 O(n²) 去了。
实测过吗?循环 1 万次 + 拼接,耗时十几秒起步;换成预先指定容量的 StringBuilder,几毫秒搞定。这不是语法之争,是量变引起质变。
编译器对静态或简单变量的拼接做了深度优化,很多人不知道这一点:
"a" + "b" + "c" → 编译期直接合入常量池,运行时零开销prefix + value + suffix → JDK 9+ 多数情况会编译成高效字节码,或者自动转成 StringBuilder 链式调用log.debug("id=" + id) 就算日志级别关闭,拼接仍然执行。该用占位符就用占位符:log.debug("id={}", id)所以,别再见到“+”就一棍子打死。关键看它在哪、拼多少次。
与其问“哪个方法更快”,不如问“哪个工具更适合当前场景”:
.concat() 更好,底层直接数组拷贝,没有额外对象创建String.join("-", list),代码简洁,内部已用 StringBuilder 实现String.format() 方便,但别放进高频执行路径里new StringBuilder(2048) 或根据预期长度估算StringBuffer 和 StringBuilder 功能一模一样,唯一的区别是前者每个 public 方法都加了 synchronized 关键字。单线程下用 StringBuffer,纯属给自己加锁开销——实测比 StringBuilder 慢 1.5 到 2 倍。多线程场景下如果要共享拼接结果,也别直接用 StringBuffer,更轻量的方案是 ThreadLocal,各线程各自拼、最后再汇总。
工具从来不是越复杂越好,而是越对症越好。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8