Scala StringBuilder的append与++=方法性能差异问题咨询
Scala StringBuilder
++= 与 append 方法性能差异说明 底层实现差异
两个方法的性能差距完全来自实现逻辑的区别,针对Scala 2.12.2版本的scala.collection.mutable.StringBuilder:
append(String)是StringBuilder专属的原生字符串拼接方法,底层直接复用Java AbstractStringBuilder的成熟实现:调用时会直接读取待拼接字符串的底层字符数组,先检查内部char缓冲区的剩余容量,容量不足时按规则完成扩容,再通过内存整块拷贝的方式把待拼接内容直接写入缓冲区,全程没有额外中间对象创建,执行路径非常短。++=是Scala给所有可变序列类型做的通用序列拼接方法,不是专门给StringBuilder设计的。这个方法的入参是IterableOnce[Char],当传入字符串时,它会先把字符串适配成Char类型的序列,通过迭代器逐个遍历字符执行追加,过程中会产生迭代器对象创建、遍历边界检查、类型适配的额外开销,完全不会走字符串整块拷贝的高效路径。
实际性能表现
如果只是拼接1、2段短字符串,两者的差距几乎感知不到;但在循环拼接多段字符串的场景下,++=的逐字符遍历逻辑会带来明显的性能损耗,通常比直接调用append慢30%到数倍,循环次数越多、单段待拼接字符串越长,性能差距就越大。
代码优化参考
只需要把原有代码里所有的++=替换成append就能拿到更好的性能,优化后代码如下:
val sourceAlias = "source" val destinationAlias = "destination" val compositeKeys = Array("Id","Name") val initialUpdateExpression = new StringBuilder("") for (key <- compositeKeys) { initialUpdateExpression.append(s"$sourceAlias.$key = $destinationAlias.$key and ") } initialUpdateExpression.append(s"$sourceAlias.Valid = $destinationAlias.Valid") val updateExpression = initialUpdateExpression.toString()
如果还要进一步提升性能,可以提前估算最终生成字符串的大致长度,初始化StringBuilder的时候直接传入初始容量参数,避免循环拼接过程中多次触发缓冲区扩容拷贝,执行效率还能再提升一截。
内容的提问来源于stack exchange,提问作者Nikunj Kakadiya
相关产品推荐
相关产品推荐

