
Java中使用+=拼接两个已知长度的字符串(如str += " world")本质上是一次O(n)操作,而非多次O(n²)迭代;其性能取决于是否在循环内反复创建新字符串对象。
java中使用`+=`拼接两个已知长度的字符串(如`str += " world"`)本质上是一次o(n)操作,而非多次o(n²)迭代;其性能取决于是否在循环内反复创建新字符串对象。
在Java中,字符串是不可变(immutable)的,这意味着每次执行 str += s 时,都会创建一个全新的String对象,其底层字符数组长度为 str.length() + s.length(),并一次性将两个源字符串的所有字符复制进去。这一过程的时间复杂度为 O(m + n),其中 m 和 n 分别是左右操作数的长度——即线性时间,而非平方级。
关键在于:编译器与JVM能静态推断字面量长度,且+=在单次调用中只触发一次内存分配与一次双路拷贝。例如:
String str = "hello"; str += " world"; // ✅ 一次分配、一次拷贝:O(5 + 6) = O(11)
该语句等价于(JVM层面):
str = new StringBuilder(str).append(" world").toString();(现代JDK中,+=会被自动优化为StringBuilder,但即使不优化,语义上也仅需一次目标数组分配和两次顺序拷贝)
立即学习“Java免费学习笔记(深入)”;
⚠️ 真正导致O(n²)的是在循环中反复拼接,例如问题中的 append1:
void append1(String s) {
String str = "hello";
for (int i = 0; i < s.length(); i++) { // 假设s.length() == k
str += s.charAt(i); // 每次都新建String:长度从5→6→7→…→5+k
}
}此时第i次迭代需复制约 (5 + i) 个字符,总操作数 ≈ 5 + 6 + 7 + ... + (5 + k − 1) = O(k²),即典型的二次复杂度。
而 append2 则完全不同:
void append2(String s) {
String str = "hello";
str += s; // ✅ 仅一次:分配长度为 5 + s.length() 的数组,拷贝全部字符
}它的时间复杂度严格为 O(5 + s.length()) = O(n),与s是否为字面量或变量无关——只要s的长度可获取(String内部缓存了count字段),JVM就能直接计算目标容量。
需要澄清一个常见误解:
❌ “编译器无法预知" world"长度” → 错。字面量长度在编译期即确定,JVM在运行时可立即读取。
✅ "hello" 和 " world" 的长度均为常量,str += " world" 的内存规划完全静态可预测。
✅ 即使是 str += s(s为变量),只要s.length()可快速返回(String的length()是O(1)),整体仍是O(m+n)。
? 总结:
- str += "literal" 或 str += variable 是一次拼接操作,时间复杂度为 O(len(str) + len(rhs));
- 在循环中执行 str += char 或 str += singleCharStr 是多次独立拼接,累积复杂度为 O(n²);
- 若需高频拼接,请始终使用 StringBuilder(显式复用缓冲区),避免隐式创建大量中间String对象。


















