We know that String objects in Java are immutable, meaning:
Once created, their content cannot change.
So, for frequent string modifications (like in loops, concatenation, or text building), immutable strings are slow and memory-inefficient.
Hence, Java provides:
-
StringBuffer→ mutable + thread-safe -
StringBuilder→ mutable + fast (non-thread-safe)
A mutable sequence of characters (not synchronized).
Introduced in Java 1.5 to replace StringBuffer in single-threaded programs.
| Property | Description |
|---|---|
| Mutability | ✅ Yes |
| Thread-safe | ❌ No |
| Synchronization | ❌ Not synchronized |
| Performance | Fast |
| Best Use Case | Single-threaded applications |
public class StringBuilderDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello");
sb.append(" Java"); // add text
sb.insert(5, ","); // insert comma
sb.replace(0, 5, "Hi"); // replace part
sb.delete(3, 5); // delete part
sb.reverse(); // reverse string
System.out.println(sb);
}
}Output:
avaJ,iH
| Method | Description | Example |
|---|---|---|
append() |
Adds text at end | sb.append(" World") |
insert(int, String) |
Inserts text at position | sb.insert(5, "Java") |
replace(int, int, String) |
Replace substring | sb.replace(0, 5, "Hi") |
delete(int, int) |
Delete substring | sb.delete(2, 5) |
reverse() |
Reverses sequence | sb.reverse() |
capacity() |
Returns buffer size | sb.capacity() |
ensureCapacity(int) |
Ensures buffer capacity | sb.ensureCapacity(100) |
setLength(int) |
Truncates or pads | sb.setLength(10) |
-
Uses a character array buffer internally.
-
Initial capacity = 16 characters (by default).
-
When buffer is full → grows automatically using:
newCapacity = (oldCapacity * 2) + 2
Example:
StringBuilder sb = new StringBuilder();
System.out.println(sb.capacity()); // 16
sb.append("abcdefghijklmnopq"); // exceeds 16
System.out.println(sb.capacity()); // (16*2)+2 = 34public class BuilderPerformance {
public static void main(String[] args) {
long start, end;
StringBuilder sb = new StringBuilder();
start = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
sb.append(i);
end = System.currentTimeMillis();
System.out.println("StringBuilder time: " + (end - start) + "ms");
}
}✅ Much faster than using normal String concatenation inside loops.
A mutable sequence of characters like StringBuilder,
but thread-safe (all methods are synchronized).
Introduced in Java 1.0 (legacy class).
| Property | Description |
|---|---|
| Mutability | ✅ Yes |
| Thread-safe | ✅ Yes |
| Synchronization | ✅ Synchronized |
| Performance | 🐢 Slower (due to locking) |
| Best Use Case | Multi-threaded programs |
public class StringBufferDemo {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("Hello");
sb.append(" World");
sb.insert(6, "Java ");
sb.delete(0, 6);
sb.reverse();
System.out.println(sb);
}
}Output:
dlroW avaJ
| Method | Description |
|---|---|
append() |
Add text at end |
insert() |
Insert text |
delete() |
Remove characters |
reverse() |
Reverse string |
capacity() |
Show current buffer capacity |
trimToSize() |
Reduce buffer to actual size |
public class ThreadSafetyDemo {
public static void main(String[] args) throws InterruptedException {
StringBuffer buffer = new StringBuffer();
Runnable r = () -> {
for(int i = 0; i < 1000; i++) {
buffer.append("x");
}
};
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Length = " + buffer.length()); // Expected 2000
}
}✅ Output is always correct because methods are synchronized.
If you replace StringBuffer with StringBuilder → ❌ unpredictable results (not thread-safe).
Before split() existed, Java had the StringTokenizer class to break a string into tokens (words, pieces, etc.).
A legacy class from java.util used to divide strings into tokens based on delimiters.
import java.util.StringTokenizer;
public class TokenizerDemo {
public static void main(String[] args) {
String text = "Java,Python,C++,Go";
StringTokenizer st = new StringTokenizer(text, ",");
while(st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
}
}Output:
Java
Python
C++
Go
| Constructor | Description |
|---|---|
StringTokenizer(String str) |
Uses default delimiter (space) |
StringTokenizer(String str, String delim) |
Custom delimiter |
StringTokenizer(String str, String delim, boolean returnDelims) |
Option to return delimiters as tokens |
String data = "apple,banana;grapes.orange";
StringTokenizer st = new StringTokenizer(data, ",;.");
while(st.hasMoreTokens()) {
System.out.println(st.nextToken());
}Output:
apple
banana
grapes
orange
-
StringTokenizeris deprecated in modern Java usage. -
Prefer using:
String[] parts = str.split("[,;.]");
or
Scanner scanner = new Scanner(str);
-
String→ Immutable -
StringBuilder→ Mutable + Fast (not thread-safe) -
StringBuffer→ Mutable + Safe (thread-safe, slower) -
StringTokenizer→ Legacy, replaced bysplit()andScanner
-
Q: Why use
StringBuilderoverStringfor concatenation? A: To avoid creating multiple temporary string objects (faster and memory-efficient). -
Q: How does
StringBuildergrow internally? A: Automatically doubles capacity (newCap = oldCap * 2 + 2). -
Q: Can
StringBufferandStringBuilderbe converted toString? A: Yes, using.toString()method. -
Q: Is
StringTokenizerstill used? A: Rarely. It’s considered legacy;String.split()or regex are preferred.