StringBuilder
In a string
append, a new string
must be created—a string
cannot be changed. But with StringBuilder
in Scala 3.3 we add data to an internal buffer.
With the new keyword, we create StringBuilders
in Scala. With methods on the StringBuilder
we append, insert, remove data. We can convert to a string
.
Here we create a new StringBuilder
called "builder." We use val
to have a constant variable—but the internal data of the StringBuilder
can still be changed.
Append()
receives many types of arguments. But most commonly we add strings to a StringBuilder
.StringBuilder
. We can use "size" as an alternative.string
to pass to another function as an argument. With toString
we convert the StringBuilder
to a string
.object Program { def main(args: Array[String]): Unit = { // Create a new StringBuilder. // ... Append 2 strings. val builder = new StringBuilder() builder.append("cat ") builder.append("bird") // Print the StringBuilder and its length. println(builder) println(builder.length) // Convert StringBuilder to a string. val result = builder.toString() println(result) } }cat bird 8 cat bird
Append
charactersHere is a more complex example. We process a custom format string
. We have special characters in a string
, and then insert values as we build up a StringBuilder
.
string
with a for
-loop. When the special chars are encountered, we append Ints to the StringBuilder
.StringBuilder
has numbers in place of the format chars. We use toString
to get a final string
representation.object Program { def main(args: Array[String]): Unit = { // Use this as a custom format string. val format = "Cats: @, dogs: %" println(format) // Create a new StringBuilder. val builder = new StringBuilder() val cats = 10 val dogs = 20 // Loop over the format string. // ... Append values in place of format characters. for (i <- format.indices) { if (format(i) == '@') { builder.append(cats) } else if (format(i) == '%') { builder.append(dogs) } else { builder.append(format(i)) } } // Print the results. val result = builder.toString() println(result) } }Cats: @, dogs: % Cats: 10, dogs: 20
Insert
, replaceA StringBuilder
's buffer is mutable. This makes operations like insert and replace faster. Here we test these functions.
string
beginning at an index. Later characters are moved to be after the new string
.Replace()
receives a start index, and an end index (not a length). We replace the first char
with the arguments 0, 1.object Program { def main(args: Array[String]): Unit = { val builder = new StringBuilder() // Append initial data. builder.append("I like cats") println(builder) // Insert this string at index 1. builder.insert(1, " do not") println(builder) // Replace first character with a new string. builder.replace(0, 1, "You") println(builder) } }I like cats I do not like cats You do not like cats
charAt
We access StringBuilder
characters with an index. We can directly use the index or call charAt
. The first char
is at 0, and the last is at the length minus one.
object Program { def main(args: Array[String]): Unit = { val letters = new StringBuilder() letters.append("abc") // Get the first char. // ... We can access the builder like a list or array. val firstChar = letters(0) // Use charAt to get second and last chars. val secondChar = letters.charAt(1) val lastChar = letters.charAt(letters.length - 1) // Print our characters. println(firstChar) println(secondChar) println(lastChar) } }a b c
When accessing characters in a StringBuilder
we must be careful to address an existing slot. Otherwise the "String
index out of range" exception will appear.
object Program { def main(args: Array[String]): Unit = { val names = new StringBuilder() names.append("mars") // This will cause an error. val c = names(400) } }java.lang.StringIndexOutOfBoundsException: Index 400 out of bounds for length 4...
In Scala, StringBuilder
is a performance optimization, but it is a necessary one. It optimizes appending (or inserting, or replacing) many strings at once, with no allocations.