String - StringBuffer - StringBuilder trong Java
String
String là một lớp cơ bản để biểu diễn chuỗi trong Java. Tuy nhiên trong Java, String là bất biến(immutable) - tức là không thể sửa đổi được. Nghĩa là một khi một đối tượng String được tạo ra, thì nó không thể thay đổi nội dung của mình. Nếu chương trình của bạn cần thực hiện nhiều thay đổi trên một chuỗi, sử dụng String làm lãng phí tài nguyên và làm chương trình chạy chậm.
Example:
public class Example{ public static void main(String[] args) { String a = "String a"; a = a + "a"; } }
Ở ví dụ trên:
String a
= "String aa", nhìn vào thì ta tưởng là đã nối thành công chữ "a" vào sau "String a" để thành kết quả như vậy nhưng không, chúng ta vừa tạo một vùng nhớ mới chứa giá trị "String aa" và lại dùng biếna
trỏ tới vị trí của giá trị mới, còn giá trị cũ mà biếna
trỏ tới là "String a" không được ai truy cập tới nên nó sẽ được bộ dọn rác lụm.
StringBuffer
StringBuffer là một lớp có khả năng sửa đổi được(mutable) và được thiết kế để hỗ trợ đa luồng (multi-threaded). Khi bạn thực hiện bất kỳ thao tác nào nên một đối tượng StringBuffer, nội dung của nó sẽ được sửa đổi trực tiếp mà không cần tạo ra một đối tượng mới. Điều này làm cho StringBuffer được sử dụng trong các tình huống đa luồng, nơi mà nhiều luồng có thể truy cập và thay đổi cùng một đối tượng StringBuffer.
Note: StringBuffer là một lớp được đồng bộ hóa (synchronized). Nó cho phép trong khi một luồng đang sử dụng đối tượng StringBuffer để thực hiện tao tác sửa đổi thì các luồng khác cần sửa đổi nội dung trên đối tượng StringBuffer đó phải chờ đợi luồng đang thực hiện kết thúc thao tác của mình mới tới lượt. Điều này giúp đảm bảo các thao tác của các luồng trên cùng một đối tượng StringBuffer đó được an toàn trong tình huống đa luồng.
Example:
public class StringBufferExample { public static void main(String[] args) { StringBuffer sb = new StringBuffer(); Thread thread1 = new Thread(() -> { sb.append("Hello"); }); Thread thread2 = new Thread(() -> { sb.append("World"); }); thread1.start(); thread2.start(); try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } String result = sb.toString(); System.out.println(result); }
}
Trong ví dụ trên, chúng ta sử dụng lớp StringBuffer để ghép các chuỗi "Hello" và "World" lại với nhau. Tuy nhiên, chương trình chạy trên hai luồng khác nhau và thực hiện các thao tác trên đối tượng StringBuffer chung. Do đó, chúng ta cần sử dụng StringBuffer để đảm bảo rằng các thao tác trên chuỗi được thực hiện một cách an toàn trong các tình huống đa luồng.
Note: Phương thức
join()
của Thread trong java được sử dụng để chờ một luồng kết thúc trước khi tiếp tục thực hiện các lệnh tiếp theo trong 1 chương trình. Khi một luồng gọi phương thứcjoin()
của một luồng khác, luồng đang gọi sẽ bị tạm dừng và không thực hiện các lệnh tiếp theo cho đến khi luồng được chờ kết thúc.Ở ví dụ trên: chúng ta sử dụng câu lệnh
thread1.join()
vàthread2.join()
để chương trình đợi "thread1" và "thread2" kết thúc trước khi kết thúc chương trình. Nếu không chương trình sẽ in ra kết quả là String rỗng.
StringBuilder
Giống với StringBuffer, StringBuilder là một lớp có khả khả năng sửa đổi được(mutable) và được thiết kế hỗ trợ đơn luồng (single-threaded). Tương tự như StringBuffer, khi cần thực hiện bất kỳ tao tác sửa đổi nào trên một đối tượng StringBuilder, nội dung của nó sẽ được thay đổi trực tiếp và không tạo ra một đối tượng mới. Tuy nhiên, do không cần hỗ trợ đa luồng nên StringBuilder có thể nhanh hơn so với StringBuffer.
Example:
public class StringBuilderExample { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append("Hello"); sb.append(" "); sb.append("World"); String result = sb.toString(); System.out.println(result); }
}
Trong ví dụ trên, chúng ta sử dụng lớp StringBuilder để ghép các chuỗi "Hello" và "World" lại với nhau. Vì chương trình chỉ chạy trên một luồng (đơn luồng), chúng ta không cần phải lo lắng về việc đồng bộ hóa và có thể sử dụng StringBuilder để tăng hiệu suất của chương trình.