String vs StringBuilder vs StringBuffer

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 5 min

TL;DR

FeatureStringStringBuilderStringBuffer
MutabilityImmutableMutableMutable
Thread SafetySafeNot SafeSafe (Synchronized)
PerformanceSlow (if concatenated)FastSlow (due to locks)

Concept

Because String objects are immutable, repeatedly concatenating them (e.g., inside a loop) is extremely inefficient. Every concatenation creates a brand new String object, consuming memory and CPU.

To solve this, Java provides Mutable string classes:

  1. StringBuilder: A mutable sequence of characters. It is the preferred class for modifying strings because it is very fast.
  2. StringBuffer: Exactly like StringBuilder, but all of its methods are synchronized. This makes it thread-safe (multiple threads can use it safely), but significantly slower.

Examples

public class StringPerformance {
    public static void main(String[] args) {
        // 1. Inefficient (Creates 1000 new String objects!)
        String str = "";
        for (int i = 0; i < 1000; i++) {
            str += i; 
        }
        
        // 2. Efficient (Modifies the existing internal array)
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 1000; i++) {
            sb.append(i);
        }
        String result = sb.toString();
        
        // 3. Thread-Safe (Use only when accessed by multiple threads concurrently)
        StringBuffer buffer = new StringBuffer();
        buffer.append("Safe");
    }
}

Interview Questions

Q: When should you use StringBuilder over String?
A: You should use StringBuilder whenever you are constructing a string dynamically inside a loop, or combining many separate strings, to avoid the overhead of creating numerous temporary immutable String objects.

Q: Since Java 8/9, does the compiler automatically optimize String concatenation?
A: Yes. If you write String s = "a" + "b" + "c";, the compiler optimizes this automatically (historically using StringBuilder under the hood, and since Java 9 using StringConcatFactory via invokedynamic). However, the compiler cannot optimize concatenations that occur across multiple iterations of a for or while loop. You must explicitly use StringBuilder for loops.