恶意不息免安装绿色中文版
42.6G · 2025-11-05
原文来自于:zha-ge.cn/java/29
那是一个阳光明媚的周二下午,我正在为公司的日志系统写一个数据处理模块。需求很简单:把几千条用户操作记录拼接成一个大字符串,然后写入文件。
我满怀信心地写下了这样的代码:
String result = "";
for (LogRecord record : logRecords) {
result += record.getTimestamp() + " | " + record.getUserId() + " | " + record.getAction();
// ... 其他字段拼接
}
测试时发现,当数据量达到 1 万条时,程序居然跑了 30 多秒!我的第一反应是:"这不科学啊,就是个字符串拼接而已。"
经过一番调研,我才恍然大悟。原来 Java 中的 String 就像是一个"顽固的老头"——不可变(Immutable)。每次看似简单的 += 操作,实际上都会:
想象一下,1 万次循环就是 1 万次"搬家",难怪这么慢!
同事小李看到我愁眉苦脸的样子,神秘一笑:"兄弟,试试 StringBuilder 吧。"
StringBuilder sb = new StringBuilder();
for (LogRecord record : logRecords) {
sb.append(record.getTimestamp())
.append(" | ")
.append(record.getUserId())
.append(" | ")
.append(record.getAction());
}
String result = sb.toString();
这次测试结果让我惊呆了——同样的 1 万条数据,只用了不到 1 秒!
StringBuilder 就像一个"可扩展的购物袋",内部维护一个字符数组。当空间不够时,它会自动扩容,而不是每次都换个新袋子。
正当我为找到神器而沾沾自喜时,生产环境出现了奇怪的问题:偶尔会出现字符串内容错乱。经过排查发现,多个线程在并发操作同一个 StringBuilder 实例!
原来 StringBuilder 是线程不安全的。在多线程环境下,它就像是几个人同时往一个袋子里塞东西,结果可想而知。
这时候,StringBuffer 闪亮登场了:
StringBuffer buffer = new StringBuffer();
// 在多线程环境下安全使用
buffer.append("线程安全的字符串拼接");
经过这次"血泪教训",我总结了三者的核心特点:
| 特性 | String | StringBuilder | StringBuffer |
|---|---|---|---|
| 可变性 | 不可变 | 可变 | 可变 |
| 线程安全 | 安全 | 不安全 | 安全 |
| 性能 | 最慢 | 最快 | 中等 |
| 内存开销 | 大 | 小 | 小 |
这次探险让我明白了几个道理:
现在,当新同事问我字符串拼接用什么时,我总是会问:"单线程还是多线程?性能要求高吗?"
毕竟,选择合适的工具,就像给脚穿合适的鞋——只有合脚,才能走得更远。
小贴士:在现代 Java 版本中,编译器会自动将简单的字符串拼接优化为 StringBuilder,但复杂场景下,手动选择仍然是最佳实践。
42.6G · 2025-11-05
37.9G · 2025-11-05
33.7G · 2025-11-05
2025-11-05
AI 推理性能大提升:华为 UCM 技术开源,系统吞吐猛增 22 倍
2025-11-05
苹果 Creator Studio 品牌曝光,预估为 Final Cut Pro 等应用“全家桶”订阅