Is string interpolation more performant than concatenation to build a string in scala? For example:
val myVal = "def"
val test = s"abs${myVal}ghi"
vs
val test = "abc" + myVal + "ghi"
I am asking because I need to write the toString
method for a class
which has a lot of parameters and the interpolated string therefore gets really long and confusing and I would like to break it up into multiple lines but fear that it will perform badly if I concatenate.
Whenever a change to a String is made, an entirely new String is created. Concatenation is the process of joining end-to-end.
An interpolated string is a string literal that might contain interpolation expressions. When an interpolated string is resolved to a result string, items with interpolation expressions are replaced by the string representations of the expression results.
There are two ways to concatenate strings in Java: By + (String concatenation) operator. By concat() method.
Concatenation is the process of appending one string to the end of another string. You concatenate strings by using the + operator. For string literals and string constants, concatenation occurs at compile time; no run-time concatenation occurs. For string variables, concatenation occurs only at run time.
I made a simple example:
class Employee(name: String, age: Int) {
private var s = 0.0
def salary = s
def salary_=(s: Double) = this.s = s
def toStringConcat(): String = {
"Name: " + name + ", age: " + age + ", salary: " + salary
}
def toStringInterpol(): String = {
s"Name: $name, age: $age, salary: $salary"
}
}
object Program {
val empl = new Employee("John", 30)
empl.salary = 10.50
val times = 10000000;
def main(args: Array[String]): Unit = {
// warming-up
val resultConcat = empl.toStringConcat
val resultInterpol = empl.toStringInterpol
println("Concat -> " + resultConcat)
println("Interpol -> " + resultInterpol)
val secondsConcat0 = run(empl.toStringConcat)
val secondsInterpol0 = run(empl.toStringInterpol)
val secondsConcat1 = run(empl.toStringConcat)
val secondsInterpol1 = run(empl.toStringInterpol)
println("Concat-0: " + secondsConcat0 + "s")
println("Concat-1: " + secondsConcat1 + "s")
println("Interpol-0: " + secondsInterpol0 + "s")
println("Interpol-1: " + secondsInterpol1 + "s")
}
def run(call: () => String): Double = {
val time0 = System.nanoTime()
var result = ""
for (i <- 0 until times) {
result = call()
}
val time1 = System.nanoTime()
val elapsedTime = time1 - time0;
val seconds = elapsedTime / 1000000000.0;
seconds
}
}
Results were the following:
Concat -> Name: John, age: 30, salary: 10.5
Interpol -> Name: John, age: 30, salary: 10.5
Concat-0: 2.831298161s
Concat-1: 2.725815448s
Interpol-0: 3.846891864s
Interpol-1: 3.753401004s
Interpolation case was slower. The reason can be found in generated code:
public String toStringConcat()
{
return new StringBuilder().append("Name: ").append(this.name).append(", age: ").append(BoxesRunTime.boxToInteger(this.age)).append(", salary: ").append(BoxesRunTime.boxToDouble(salary())).toString();
}
public String toStringInterpol()
{
return new StringContext(Predef..MODULE$.wrapRefArray((Object[])new String[] { "Name: ", ", age: ", ", salary: ", "" })).s(Predef..MODULE$.genericWrapArray(new Object[] { this.name, BoxesRunTime.boxToInteger(this.age), BoxesRunTime.boxToDouble(salary()) }));
}
I used Scala 2.10.3 and IntelliJ IDEA 13.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With