for循环中字符串拼接执行过慢,寻求优化解决方案
哇,7分钟确实太夸张了——这坑我刚入行的时候也踩过,当时调试半天没搞懂为啥循环拼接这么慢!核心原因其实很简单:你用的string在绝大多数编程语言里(比如C#、Java)都是不可变类型,每次执行str += ...的时候,并不是在原字符串后面追加内容,而是会创建一个全新的字符串对象,还要把原来的所有内容和新内容都复制到这个新对象里。循环10万次的话,这种复制的开销会滚雪球一样越来越大,最终导致耗时爆炸。
下面给你几个立竿见影的优化方案:
优先使用可变字符串类
几乎所有主流语言都提供了专门用于频繁拼接的可变字符串工具,比如:- C#/Java:用
StringBuilder(Java里StringBuffer是线程安全版,单线程场景用StringBuilder更快) - Python:用列表暂存片段再
join
拿C#举个例子,改写后的代码应该是这样:
StringBuilder sb = new StringBuilder(); for(int i=0; i<100000; i++){ // 原来的逻辑,把str += ...换成sb.Append(...) sb.Append(...); } return sb.ToString();这个类内部用可扩容的数组存储内容,拼接操作几乎是均摊O(1)的时间复杂度,用它的话,你的代码执行时间应该会直接降到毫秒级,绝对不会再等7分钟。
- C#/Java:用
预先指定容量(可选,进一步提速)
如果你能大概估算出最终字符串的长度,初始化StringBuilder的时候直接指定容量,就能避免内部数组频繁扩容的额外开销。比如你预估最终字符串有100万字符,就这么写:StringBuilder sb = new StringBuilder(1000000);这样
StringBuilder会直接分配足够大的数组,不用中途反复扩容复制,性能还能再上一个台阶。Python用户的特殊优化
如果你用的是Python,别用循环str +=,而是把所有要拼接的片段放进一个列表,最后用''.join(parts)一次性拼接:parts = [] for i in range(100000): parts.append(...) # 把要拼接的内容添加到列表 return ''.join(parts)列表的
append操作是O(1)的,而join方法会一次性计算总长度并分配内存,比循环拼接高效太多。
总结一下:本质就是避免每次拼接都复制整个字符串,用可变容器或者批量拼接的方式,把线性的时间复杂度降到近似O(n),性能提升简直是天差地别。
内容的提问来源于stack exchange,提问作者asady

