Skip to content

Instantly share code, notes, and snippets.

@kristopherjohnson
Last active March 12, 2024 19:07
Show Gist options
  • Save kristopherjohnson/1fc55e811d944a430289 to your computer and use it in GitHub Desktop.
Save kristopherjohnson/1fc55e811d944a430289 to your computer and use it in GitHub Desktop.
A StringBuilder class for Swift
/**
Supports creation of a String from pieces
*/
public class StringBuilder {
private var stringValue: String
/**
Construct with initial String contents
:param: string Initial value; defaults to empty string
*/
public init(string: String = "") {
self.stringValue = string
}
/**
Return the String object
:return: String
*/
public func toString() -> String {
return stringValue
}
/**
Return the current length of the String object
*/
public var length: Int {
return countElements(stringValue)
}
/**
Append a String to the object
:param: string String
:return: reference to this StringBuilder instance
*/
public func append(string: String) -> StringBuilder {
stringValue += string
return self
}
/**
Append a Printable to the object
:param: value a value supporting the Printable protocol
:return: reference to this StringBuilder instance
*/
public func append<T: Printable>(value: T) -> StringBuilder {
stringValue += value.description
return self
}
/**
Append a String and a newline to the object
:param: string String
:return: reference to this StringBuilder instance
*/
public func appendLine(string: String) -> StringBuilder {
stringValue += string + "\n"
return self
}
/**
Append a Printable and a newline to the object
:param: value a value supporting the Printable protocol
:return: reference to this StringBuilder instance
*/
public func appendLine<T: Printable>(value: T) -> StringBuilder {
stringValue += value.description + "\n"
return self
}
/**
Reset the object to an empty string
:return: reference to this StringBuilder instance
*/
public func clear() -> StringBuilder {
stringValue = ""
return self
}
}
/**
Append a String to a StringBuilder using operator syntax
:param: lhs StringBuilder
:param: rhs String
*/
public func += (lhs: StringBuilder, rhs: String) {
lhs.append(rhs)
}
/**
Append a Printable to a StringBuilder using operator syntax
:param: lhs Printable
:param: rhs String
*/
public func += <T: Printable>(lhs: StringBuilder, rhs: T) {
lhs.append(rhs.description)
}
/**
Create a StringBuilder by concatenating the values of two StringBuilders
:param: lhs first StringBuilder
:param: rhs second StringBuilder
:result StringBuilder
*/
public func +(lhs: StringBuilder, rhs: StringBuilder) -> StringBuilder {
return StringBuilder(string: lhs.toString() + rhs.toString())
}
// Examples
let sb = StringBuilder()
sb.append(1).append("+").append(1).append("=").append(2)
sb.toString()
let sb2 = StringBuilder()
sb2 += "2+2"
sb2 += "="
sb2 += "4"
sb2.toString()
let sbAdd = sb + sb2
sbAdd.toString()
@thbwd
Copy link

thbwd commented Sep 10, 2015

Why should I anyone use this class? That’s just overhead isn’t it?

@lyahdav
Copy link

lyahdav commented Nov 8, 2015

I also don't understand why someone would use this class. Swift's String class already has a += operator and an appendContentsOf methods to concatenate strings. I came here expecting a Swift implementation of Java's StringBuilder class which efficiently allows you to build up a string, but this is not it.

@quickthyme
Copy link

This class is apparently intended to be a replacement for Java.lang.StringBuilder (StringBuffer) class in Swift. It is handy if you ever need to port working Java code over to Swift, and you don't want to change the existing code structure for whatever reason. (e.g. You're working on a project that will target both iOS and Android.)

@GuyKahlon
Copy link

@quickthyme @lyahdav @idmean @kristopherjohnson

I'm considering implementing a StringBuilder version for Swift.
I wonder if it's necessary.

The reason I wonder to implement this is because I'm not sure about the run time comlxisty of the method 'joinWords':

 func joinWords(words: [String]) -> String {
    var sentence = ""
    for w in words {
      sentence += w
    }
    return sentence
  }

If one each concatenating, a new copy of the string is created, and the two strings are copied over, character by character. The first iteration requires us to copy X characters. The second iteration requires copying 2X characters. The third iteration requires 3X, and so on. The total time therefore is O(X + 2X + 3X …… nX) this reduce to O(Xn^2).

And of course we can implement it with O(Xn) with StringBuilder.

I'v tried to find on the Apple docmentntion about the run time complexity of the + operation, but without success.

Thanks,
Guy

@wjxiz
Copy link

wjxiz commented Jul 12, 2016

very helpful . Thanks

@pawelnathan
Copy link

Since swift compiler likes to hang, when used with many string concated together, this is very useful to me. Many thanks

@tonsnoei
Copy link

This whole class does not make any sense as long as it is build up on: stringValue += string. Normally a StringBuilder is used (C#, Java) to provide a, performance- and memory-wise, better solution than a simple string concatination (which introduces a lot of overhead).

@mingynaut
Copy link

While this comment is extremely 'late to the table',
Thanks for building this class. I was unable to use the Printable protocol. However, there is a need for a StringBuilder class similar to the Java equivalent. Although some may have never been exposed to java, StringBuilder and other java classes serve as a good model to use for some missing pieces in Swift. And yes, I needed it to build up a Json string from many pieces, and it does help. The complier did complain when I did the old 'stringValue += string' This class does solve that problem. I am not sure what the Printable protocol is? requires a description func? Anyway, thank you for taking the time and then posting it for some of the more gracious of us to use.

@kristopherjohnson
Copy link
Author

kristopherjohnson commented Feb 28, 2020

This was written for a very early version of Swift. As noted in other comments, it is not needed with the current String interface. Just use += or interpolated strings.

@jonreid
Copy link

jonreid commented May 11, 2022

…That said, I just encountered the first case where I needed a reference object to which I can send append messages.

@lyahdav
Copy link

lyahdav commented Mar 12, 2024

@GuyKahlon a bit late here, but I discovered that Swift's String class uses an exponential growth strategy that makes appending to a string a constant time operation when averaged over many appends. See here for the source. So this means that there's no need for a StringBuilder class in Swift as using += on a swift String is already doing the performant thing that Java's StringBuilder class is doing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment