22

Groovy supports a literal syntax for creating a StringBuilder/StringBuffer instead of the usual

def sb = new StringBuilder()

However, I can't seem to remember (or find on Google) the correct syntax.

Dónal
  • 185,044
  • 174
  • 569
  • 824

4 Answers4

26

To get a StringBuffer in a single step, you could use

def sb = 'Hello'<<''

or even:

def sb = ''<<'' //4 single quotes, not double quotes

for an initially empty one.

I think (but I could be wrong) the reason for using a StringBuffer rather than a StringBuilder is to maintain compatibility with Java 1.4.

matt
  • 78,533
  • 8
  • 163
  • 197
16

To create a StringBuffer:

text = 'Hello '

To append:

text <<= 'World!'

And this might help some more.

willkil
  • 1,619
  • 1
  • 21
  • 33
omerkudat
  • 9,371
  • 4
  • 33
  • 42
  • 3
    It seems that that text is converted from a String to a StringBuilder only when the '<<=' operator is used, correct? Also, it's actually a StringBuffer not a StringBuilder – Dónal Nov 25 '09 at 15:20
  • 1
    Yes, in fact my example might be overly simplistic. You do need to convert and reassign to StringBuffer, as such the `<<=` operator. Later you can just use `<<`. Also you are right about the `StringBuffer`, which is how they allowed in-place character replacement using the `[]` operator. – omerkudat Nov 25 '09 at 15:30
14

I've just played with StringBuilder / StringBuffer in Groovy.

Some examples below:

// << operator example
def year = StringBuilder.newInstance()
year << 2
year << "0"
year << '1' << 4
assert year.toString() == "2014"

// You can use with operator
def month = StringBuilder.newInstance()
month.with {
    append "0"
    append '5'
}
assert month.toString() == "05"

// or just append String like in Java or you can leave parenthesis
def day = StringBuilder.newInstance()
day.append "1"
day.append('1')
assert day.toString() == '11'

// It's nice to know, that we can use StringBuilder directly in GString
def date = "$year-${month}-$day"
assert date == "2014-05-11"

Note: Use StringBuilder when it is used only by one thread. StringBuilder provides an API compatible with StringBuffer. StringBuffer is synchronized, StringBuilder is not. Check this link for more info.

Community
  • 1
  • 1
Michal Zmuda
  • 5,381
  • 3
  • 43
  • 39
  • There's nothing special about using StringBuilder directly in GString: "[any Groovy expression is valid](http://groovy-lang.org/syntax.html#_string_interpolation)". The [official documentation](http://groovy-lang.org/syntax.html#_string_interpolation) shows `"The sum of 2 and 3 equals ${2 + 3}"` as an example. – willkil Mar 11 '19 at 15:46
2

String.leftShift() creates a StringBuffer.

AFAICS, you cannot create a StringBuilder via groovy syntax sugar. You can only create a StringBuilder explicitly. No operator overload on String or GString creates a StringBuilder that you can explicitly use. Java String concatenation might create a StringBuilder, but that instance wouldn't be usable in your code.

At the time of writing this answer:

  • Another answer said to use <<=. <<= is merely a java compound assignment that uses <<. In particular, there is no method for overloading <<=.
  • The accepted answer said to use ''<<'' //4 single quotes, not double quotes. Double quotes work fine, at least on modern groovy.

The following code shows that we always get a StringBuffer, not a StringBuilder, for the result of various combinations of << vs <<= and "" vs '':

def ls = ''<<''
println ls.class
def lse = ''
lse <<=''
println lse.class

ls = ""<<''
println ls.class
lse = ""
lse <<=''
println lse.class

ls = ''<<""
println ls.class
lse = ''
lse <<=""
println lse.class

ls = ""<<""
println ls.class
lse = ""
lse <<=""
println lse.class

prints:

class java.lang.StringBuffer
class java.lang.StringBuffer
class java.lang.StringBuffer
class java.lang.StringBuffer
class java.lang.StringBuffer
class java.lang.StringBuffer
class java.lang.StringBuffer
class java.lang.StringBuffer
willkil
  • 1,619
  • 1
  • 21
  • 33