String và StringBuffer đều dùng để xử lý chuỗi, nhưng có bản chất khác nhau về tính bất biến (immutability), đồng bộ hóa (synchronization) và hiệu năng.
Bảng so sánh chi tiết
| Tiêu chí | String | StringBuffer |
|---|---|---|
| Tính bất biến | Immutable – không thể thay đổi nội dung sau khi tạo. Mọi thao tác "sửa" tạo object mới. | Mutable – có thể thay đổi nội dung (append, insert, delete, reverse...) trên cùng object. |
| Đồng bộ hóa (Thread-safe) | Không synchronized (nhưng an toàn nhờ immutable). | Tất cả public methods đều synchronized – thread-safe. |
| Hiệu năng | Nhanh cho đọc, so sánh, hash. Chậm khi nối chuỗi nhiều lần (tạo nhiều object rác). | Chậm hơn do overhead synchronized. Tốt cho nối chuỗi nhiều lần trong multi-thread. |
| Vùng nhớ | String literal → String Constant Pool (SCP). new String() → Heap. | Luôn trên Heap. |
| Kế thừa | final class – không thể kế thừa. | Không final – có thể kế thừa (nhưng hiếm dùng). |
| Phương thức nổi bật | substring, split, replace, toUpperCase, equals, hashCode... | append, insert, delete, reverse, capacity, ensureCapacity... |
Ví dụ String (Immutable)
public class StringExample {
public static void main(String[] args) {
String s1 = "Hello";
String s2 = s1.toUpperCase(); // Tạo object mới "HELLO"
String s3 = s1 + " World"; // Tạo object mới "Hello World"
System.out.println(s1); // "Hello" (giữ nguyên)
System.out.println(s2); // "HELLO"
System.out.println(s3); // "Hello World"
// Nối chuỗi trong vòng lặp – KHÔNG KHUYẾN NGHỊ với String
String result = "";
for (int i = 0; i < 1000; i++) {
result += i; // Tạo 1000 object String rác!
}
}
}
Ví dụ StringBuffer (Mutable, Thread-safe)
public class StringBufferExample {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("Hi");
sb.append(" Java 8"); // Sửa trực tiếp trên sb
sb.insert(0, "Start: "); // Chèn ở đầu
sb.reverse(); // Đảo ngược: "8 avaJ :tratS iH"
System.out.println(sb); // In kết quả sau reverse
// Nối chuỗi hiệu quả trong loop
StringBuffer efficient = new StringBuffer();
for (int i = 0; i < 1000; i++) {
efficient.append(i); // Chỉ 1 object, mở rộng buffer nội bộ
}
}
}
StringBuilder – Anh em của StringBuffer
StringBuilder (Java 5+) giống StringBuffer nhưng KHÔNG synchronized → nhanh hơn, dùng cho single-thread (phổ biến nhất hiện nay).
Khi nào dùng cái nào?
- String: Chuỗi hằng, key map, ít thay đổi, cần thread-safe tự nhiên.
- StringBuilder: Xây dựng chuỗi động, single-thread (log, SQL building, JSON, v.v.) – Mặc định khuyên dùng.
- StringBuffer: Xây dựng chuỗi động, multi-thread chia sẻ cùng buffer (hiếm gặp).
Mẹo: toString()
Cả StringBuffer và StringBuilder đều có toString() trả về String immutable – dùng khi cần kết quả cuối cùng.