46

In Java, it's a common best practice to do string concatenation with StringBuilder due to the poor performance of appending strings using the + operator. Is the same practice recommended for Scala or has the language improved on how java performs its string concatenation?

bionicseraph
  • 812
  • 1
  • 7
  • 10

4 Answers4

49

Scala uses Java strings (java.lang.String), so its string concatenation is the same as Java's: the same thing is taking place in both. (The runtime is the same, after all.) There is a special StringBuilder class in Scala, that "provides an API compatible with java.lang.StringBuilder"; see http://www.scala-lang.org/api/2.7.5/scala/StringBuilder.html.

But in terms of "best practices", I think most people would generally consider it better to write simple, clear code than maximally efficient code, except when there's an actual performance problem or a good reason to expect one. The + operator doesn't really have "poor performance", it's just that s += "foo" is equivalent to s = s + "foo" (i.e. it creates a new String object), which means that, if you're doing a lot of concatenations to (what looks like) "a single string", you can avoid creating unnecessary objects — and repeatedly recopying earlier portions from one string to another — by using a StringBuilder instead of a String. Usually the difference is not important. (Of course, "simple, clear code" is slightly contradictory: using += is simpler, using StringBuilder is clearer. But still, the decision should usually be based on code-writing considerations rather than minor performance considerations.)

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • 1
    In my case I'm very concerned about performance hence why I'm asking the question. Thanks for all the info! – bionicseraph Dec 22 '11 at 19:40
  • AFAIK, the JVM automatically treats repeated '+' concatenations in an expression the same way as it would do a stringbuffer. So there's no performance difference really. – aishwarya Dec 22 '11 at 19:48
  • @aishwarya: The JLS recommends that compilers optimize `foo + bar + baz + bip` to the equivalent of `new StringBuilder(foo).append(bar).append(baz).append(bip).toString()` and `"foo" + "bar" + "baz" + "bip"` to `"foobarbazbip"`, but those are pretty narrow cases. And I don't think JVMs (as opposed to compilers) generally do any sort of optimization along those lines, though I could be wrong. – ruakh Dec 22 '11 at 20:08
  • 12
    pet peeve: using + in a loop results in O(n^2) complexity, while using a StringBuilder in O(n). The extra objects are a minor problem; the explosion in complexity is a major one. – Philip Potter Sep 12 '12 at 06:58
  • @PhilipPotter: Good point. I've edited my answer to mention that `StringBuilder` also helps avoid "repeatedly recopying earlier portions from one string to another". – ruakh Sep 12 '12 at 13:27
21

Scalas String concatenation works the same way as Javas does.

val x = 5
"a"+"b"+x+"c"

is translated to

new StringBuilder()).append("ab").append(BoxesRunTime.boxToInteger(x)).append("c").toString()

StringBuilder is scala.collection.mutable.StringBuilder. That's the reason why the value appended to the StringBuilder is boxed by the compiler.

You can check the behavior by decompile the bytecode with javap.

kiritsuku
  • 52,967
  • 18
  • 114
  • 136
6

I want to add: if you have a sequence of strings, then there is already a method to create a new string out of them (all items, concatenated). It's called mkString.

Example: (http://ideone.com/QJhkAG)

val example = Seq("11111", "2222", "333", "444444")
val result = example.mkString
println(result) // prints "111112222333444444"
Display Name
  • 8,022
  • 3
  • 31
  • 66
2

Scala uses java.lang.String as the type for strings, so it is subject to the same characteristics.

Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681