Lớp chuỗi
Lớp này đại diện cho một chuỗi các ký tự. Tất cả các chuỗi ký tự được xác định trong các chương trình, chẳng hạn như "Đây là Chuỗi" đều là các thể hiện của lớp Chuỗi. Chuỗi có hai tính năng cơ bản:- đây là một lớp bất biến
- đây là buổi học cuối cùng
final
) và các thể hiện của lớp không thể sửa đổi sau khi tạo ( immutable
). Điều này mang lại cho lớp String một số lợi thế quan trọng:
-
Do tính bất biến, mã băm của một thể hiện của lớp String được lưu vào bộ đệm. Nó không cần phải được đánh giá mỗi lần vì giá trị trường của đối tượng sẽ không bao giờ thay đổi sau khi nó được tạo. Điều này mang lại hiệu suất cao khi sử dụng lớp này làm khóa cho
HashMap
. -
Lớp String có thể được sử dụng trong môi trường đa luồng mà không cần đồng bộ hóa bổ sung.
-
Một đặc điểm khác của lớp String là nó nạp chồng
+
toán tử " " trong Java. Vì vậy, việc nối (cộng) các chuỗi khá đơn giản:
public static void main(String[] args) {
String command = "Follow" + " " + "the" + " " + "white" + " " + "rabbit";
System.out.println(command); // Follow the white rabbit
}
Về cơ bản, việc nối chuỗi được thực hiện bởi lớp StringBuilder hoặc StringBuffer (tùy theo ý của trình biên dịch) và một phương thức append
(chúng ta sẽ nói về các lớp này sau). Nếu chúng ta thêm các thể hiện của lớp String với các thể hiện của các lớp khác thì lớp sau sẽ được rút gọn thành biểu diễn chuỗi:
public static void main(String[] args) {
Boolean b = Boolean.TRUE;
String result = "b is " + b;
System.out.println(result); //b is true
}
Đây là một thuộc tính thú vị khác của lớp String: các đối tượng của bất kỳ lớp nào có thể được chuyển thành biểu diễn chuỗi bằng cách sử dụng phương thức toString()
được xác định trong lớp Object
và được kế thừa bởi tất cả các lớp khác. Thông thường phương thức toString() trên một đối tượng được gọi ngầm. Ví dụ: khi chúng ta hiển thị một cái gì đó trên màn hình hoặc thêm một Chuỗi vào một đối tượng của lớp khác. Lớp String có thêm một tính năng nữa. Tất cả các chuỗi ký tự được xác định trong mã Java, chẳng hạn như "asdf", được lưu vào bộ nhớ đệm tại thời điểm biên dịch và được thêm vào cái gọi là nhóm chuỗi. Nếu chúng ta chạy đoạn mã sau:
String a = "Wake up, Neo";
String b = "Wake up, Neo";
System.out.println(a == b);
Chúng ta sẽ thấy true trong bảng điều khiển vì các biến a
thực sự sẽ b
tham chiếu đến cùng một phiên bản của lớp String đã được thêm vào nhóm chuỗi tại thời điểm biên dịch. Nghĩa là, các phiên bản khác nhau của lớp có cùng giá trị sẽ không được tạo và bộ nhớ sẽ được lưu.
Sai sót:
Không khó để đoán rằng lớp String chủ yếu cần thiết để làm việc với các chuỗi. Nhưng trong một số trường hợp, những đặc điểm trên của lớp String có thể chuyển từ ưu điểm thành nhược điểm. Khi các chuỗi được tạo bằng mã Java, nhiều thao tác thường được thực hiện trên chúng:- chuyển đổi chuỗi sang các thanh ghi khác nhau;
- trích xuất chuỗi con;
- nối;
- vân vân.
public static void main(String[] args) {
String s = " Wake up, Neo! ";
s = s.toUpperCase();
s = s.trim();
System.out.println("\"" + s + "\"");
}
Thoạt nhìn có vẻ như chúng tôi chỉ dịch dòng “Wake up, Neo!” thành chữ hoa, loại bỏ khoảng trắng thừa khỏi chuỗi này và gói nó trong dấu ngoặc kép. Trên thực tế, do tính bất biến của lớp String, kết quả của mỗi thao tác là các thể hiện của chuỗi mới được tạo ra và các thể hiện của chuỗi cũ bị loại bỏ, tạo ra một lượng lớn rác. Làm thế nào để tránh lãng phí bộ nhớ?
Lớp StringBuffer
Để xử lý việc tạo rác tạm thời do sửa đổi đối tượng String, bạn có thể sử dụng lớp StringBuffer. Đây làmutable
một lớp học, tức là có thể thay đổi. Một đối tượng của lớp StringBuffer có thể chứa một tập hợp ký tự cụ thể, độ dài và giá trị của chúng có thể được thay đổi bằng cách gọi một số phương thức nhất định. Hãy xem lớp này hoạt động như thế nào. Để tạo một đối tượng mới, hãy sử dụng một trong các hàm tạo của nó, ví dụ:
- StringBuffer() - sẽ tạo một đối tượng trống (không có ký tự)
- StringBuffer(String str) - sẽ tạo một đối tượng dựa trên biến str (chứa tất cả các ký tự của str trong cùng một chuỗi)
StringBuffer sb = new StringBuffer();
StringBuffer sb2 = new StringBuffer("Not empty");
Việc nối chuỗi thông qua StringBuffer trong Java được thực hiện bằng cách sử dụng append
. Nói chung, phương thức append
trong lớp StringBuffer bị quá tải theo cách nó có thể chấp nhận hầu hết mọi kiểu dữ liệu:
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
sb.append(new Integer(2));
sb.append("; ");
sb.append(false);
sb.append("; ");
sb.append(Arrays.asList(1,2,3));
sb.append("; ");
System.out.println(sb); // 2; false; [1, 2, 3];
}
Phương thức này append
trả về đối tượng mà nó được gọi (giống như nhiều phương thức khác), cho phép nó được gọi theo một “chuỗi”. Ví dụ trên có thể viết như sau:
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
sb.append(new Integer(2))
.append("; ")
.append(false)
.append("; ")
.append(Arrays.asList(1,2,3))
.append("; ");
System.out.println(sb); // 2; false; [1, 2, 3];
}
Lớp StringBuffer có một số phương thức để làm việc với chuỗi. Hãy liệt kê những cái chính:
delete(int start, int end)
— xóa một chuỗi ký tự con bắt đầu từ vị trístart
, kết thúcend
deleteCharAt(int index)
— xóa ký tự tại vị tríindex
insert(int offset, String str)
— chèn một dòngstr
vào vị tríoffset
. Phương thức nàyinsert
cũng bị quá tải và có thể nhận các đối số khác nhaureplace(int start, int end, String str)
- sẽ thay thế tất cả các ký tự từ vị trí nàystart
sang vị tríend
khác bằngstr
reverse()
- đảo ngược thứ tự của tất cả các ký tựsubstring(int start, int end)
- sẽ trả về một chuỗi con bắt đầu từ vị trí nàystart
sang vị trí khácend
substring(int start)
- sẽ trả về một chuỗi con bắt đầu từ vị trí
start
public static void main(String[] args) {
String numbers = "0123456789";
StringBuffer sb = new StringBuffer(numbers);
System.out.println(sb.substring(3)); // 3456789
System.out.println(sb.substring(4, 8)); // 4567
System.out.println(sb.replace(3, 5, "ABCDE")); // 012ABCDE56789
sb = new StringBuffer(numbers);
System.out.println(sb.reverse()); // 9876543210
sb.reverse(); // Return the original order
sb = new StringBuffer(numbers);
System.out.println(sb.delete(5, 9)); // 012349
System.out.println(sb.deleteCharAt(1)); // 02349
System.out.println(sb.insert(1, "One")); // 0One2349
}
Thuận lợi:
-
Như đã đề cập, StringBuffer là một lớp có thể thay đổi, do đó làm việc với nó không tạo ra cùng một lượng rác bộ nhớ như với String. Do đó, nếu có nhiều sửa đổi đối với chuỗi thì tốt hơn nên sử dụng
StringBuffer
. -
StringBuffer là một lớp an toàn cho luồng. Các phương thức của nó được đồng bộ hóa và các phiên bản có thể được sử dụng đồng thời bởi nhiều luồng.
Sai sót:
Một mặt, an toàn luồng là một lợi thế của lớp, mặt khác, nó là một bất lợi. Các phương thức được đồng bộ hóa chậm hơn các phương thức không được đồng bộ hóa. Đây là lúc StringBuilder phát huy tác dụng. Hãy cùng tìm hiểu xem đây là loại lớp Java nào - StringBuilder, nó có những phương thức nào và các tính năng của nó là gì.Lớp StringBuilder
StringBuilder trong Java là một lớp đại diện cho một chuỗi ký tự. Nó rất giống với StringBuffer về mọi mặt ngoại trừ tính an toàn của luồng. StringBuilder cung cấp API tương tự như StringBuffer. Hãy chứng minh điều này bằng một ví dụ quen thuộc, thay thế việc khai báo các biến từ StringBufer sang StringBuilder:public static void main(String[] args) {
String numbers = "0123456789";
StringBuilder sb = new StringBuilder(numbers);
System.out.println(sb.substring(3)); //3456789
System.out.println(sb.substring(4, 8)); //4567
System.out.println(sb.replace(3, 5, "ABCDE")); //012ABCDE56789
sb = new StringBuilder(numbers);
System.out.println(sb.reverse()); //9876543210
sb.reverse(); // Return the original order
sb = new StringBuilder(numbers);
System.out.println(sb.delete(5, 9)); //012349
System.out.println(sb.deleteCharAt(1)); //02349
System.out.println(sb.insert(1, "One")); //0One2349
}
Sự khác biệt duy nhất là StringBuffer an toàn cho luồng và tất cả các phương thức của nó đều được đồng bộ hóa, trong khi StringBuilder thì không. Đây là tính năng duy nhất. StringBuilder trong Java nhanh hơn StringBuffer do không đồng bộ hóa các phương thức. Do đó, trong hầu hết các trường hợp, ngoại trừ trong môi trường đa luồng, tốt hơn nên sử dụng StringBuilder cho chương trình Java. Chúng tôi tóm tắt mọi thứ trong một bảng so sánh của ba lớp:
Chuỗi so với StringBuffer so với StringBuilder
Sợi dây | Bộ đệm chuỗi | Trình tạo chuỗi | |
---|---|---|---|
Khả năng thay đổi | Immutable (KHÔNG) |
mutable (Đúng) |
mutable (Đúng) |
Khả năng mở rộng | final (KHÔNG) |
final (KHÔNG) |
final (KHÔNG) |
An toàn chủ đề | Có, do tính bất biến | Có, do đồng bộ hóa | KHÔNG |
Khi nào nên sử dụng | Khi làm việc với các chuỗi hiếm khi được sửa đổi | Khi làm việc với các chuỗi sẽ được sửa đổi thường xuyên trong môi trường đa luồng | Khi làm việc với các chuỗi sẽ được sửa đổi thường xuyên trong môi trường đơn luồng |
GO TO FULL VERSION