Tôi mới gặp StringBuilder
lần đầu tiên và rất ngạc nhiên vì Java đã có một String
lớp rất mạnh cho phép gắn thêm.
Tại sao lại là String
lớp thứ hai ?
Tôi có thể tìm hiểu về thêm ở đâu StringBuilder
?
Tôi mới gặp StringBuilder
lần đầu tiên và rất ngạc nhiên vì Java đã có một String
lớp rất mạnh cho phép gắn thêm.
Tại sao lại là String
lớp thứ hai ?
Tôi có thể tìm hiểu về thêm ở đâu StringBuilder
?
Câu trả lời:
String
không cho phép bổ sung. Mỗi phương thức bạn gọi trên a String
sẽ tạo ra một đối tượng mới và trả về nó. Điều này là bởi vì String
nó là bất biến - nó không thể thay đổi trạng thái bên trong của nó.
Mặt khác StringBuilder
là có thể thay đổi. Khi bạn gọi append(..)
nó sẽ thay đổi mảng ký tự bên trong, thay vì tạo một đối tượng chuỗi mới.
Do đó, sẽ hiệu quả hơn nếu có:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 500; i ++) {
sb.append(i);
}
hơn là str += i
tạo 500 đối tượng chuỗi mới.
Lưu ý rằng trong ví dụ tôi sử dụng một vòng lặp. Khi helios ghi chú trong các nhận xét, trình biên dịch sẽ tự động dịch các biểu thức String d = a + b + c
như
String d = new StringBuilder(a).append(b).append(c).toString();
Cũng lưu ý rằng có StringBuffer
thêm vào StringBuilder
. Sự khác biệt là trước đây có các phương thức đồng bộ hóa. Nếu bạn sử dụng nó như một biến cục bộ, hãy sử dụng StringBuilder
. Nếu nó xảy ra rằng nó có thể được truy cập bởi nhiều chủ đề, hãy sử dụng StringBuffer
(hiếm hơn)
Đây là một ví dụ cụ thể về lý do tại sao -
int total = 50000;
String s = "";
for (int i = 0; i < total; i++) { s += String.valueOf(i); }
// 4828ms
StringBuilder sb = new StringBuilder();
for (int i = 0; i < total; i++) { sb.append(String.valueOf(i)); }
// 4ms
Như bạn có thể thấy sự khác biệt về hiệu suất là đáng kể.
s = sb.ToString();
ở cuối để ít nhất bạn đã làm như vậy trong cả hai ví dụ (kết quả là a string
).
Lớp String là bất biến trong khi StringBuilder có thể thay đổi.
String s = "Hello";
s = s + "World";
Đoạn mã trên sẽ tạo ra hai đối tượng vì Chuỗi là bất biến
StringBuilder sb = new StringBuilder("Hello");
sb.append("World");
Đoạn mã trên sẽ chỉ tạo một đối tượng vì StringBuilder không phải là bất biến.
Bài học: Bất cứ khi nào có nhu cầu thao tác / cập nhật / nối thêm String nhiều lần, hãy sử dụng StringBuilder vì nó hiệu quả hơn so với String.
StringBuilder dùng để xây dựng các chuỗi. Cụ thể là xây dựng chúng theo một cách rất hiệu quả. Lớp String tốt cho nhiều thứ, nhưng nó thực sự có hiệu suất thực sự khủng khiếp khi lắp ráp một chuỗi mới từ các phần chuỗi nhỏ hơn vì mỗi chuỗi mới là một chuỗi hoàn toàn mới, được phân bổ lại. (Nó không thay đổi ) StringBuilder giữ nguyên trình tự giống nhau và sửa đổi nó ( có thể thay đổi ).
Lớp StringBuilder có thể thay đổi và không giống như String, nó cho phép bạn sửa đổi nội dung của chuỗi mà không cần tạo thêm đối tượng String, đây có thể là một lợi ích về hiệu suất khi bạn sửa đổi nhiều một chuỗi. Ngoài ra còn có một bản sao cho StringBuilder được gọi là StringBuffer cũng được đồng bộ hóa nên nó rất lý tưởng cho các môi trường đa luồng.
Vấn đề lớn nhất với String là bất kỳ thao tác nào bạn thực hiện với nó, sẽ luôn trả về một đối tượng mới, chẳng hạn như:
String s1 = "something";
String s2 = "else";
String s3 = s1 + s2; // this is creating a new object.
StringBuilder rất tốt khi bạn xử lý các chuỗi lớn hơn. Nó giúp bạn cải thiện hiệu suất.
Đây là một bài báo mà tôi thấy rằng hữu ích.
Một tìm kiếm nhanh trên google có thể đã giúp bạn. Bây giờ bạn đã thuê 7 người khác nhau để thực hiện tìm kiếm trên google cho bạn. :)
Nói chính xác, StringBuilder thêm tất cả các chuỗi là O (N) trong khi thêm String là O (N ^ 2). Kiểm tra mã nguồn, điều này đạt được nội bộ bằng cách giữ một mảng ký tự có thể thay đổi. StringBuilder sử dụng kỹ thuật nhân đôi độ dài mảng để đạt được hiệu suất O (N ^ 2) được khấu hao , với chi phí có khả năng tăng gấp đôi bộ nhớ cần thiết. Bạn có thể gọi trimToSize ở cuối để giải quyết điều này, nhưng thường các đối tượng StringBuilder chỉ được sử dụng tạm thời. Bạn có thể cải thiện hơn nữa hiệu suất bằng cách cung cấp một dự đoán bắt đầu tốt ở kích thước chuỗi cuối cùng.
Hiệu quả.
Mỗi khi bạn nối các chuỗi, một chuỗi mới sẽ được tạo. Ví dụ:
String out = "a" + "b" + "c";
Điều này tạo ra một chuỗi mới, tạm thời, sao chép "a" và "b" vào nó để dẫn đến "ab". Sau đó, nó tạo một chuỗi mới tạm thời khác, sao chép "ab" và "c" vào đó, để dẫn đến "abc". Kết quả này sau đó được gán choout
.
Kết quả là thuật toán của Schlemiel the Painter độ phức tạp thời gian O (n²) (bậc hai).
StringBuilder
, mặt khác, cho phép bạn nối các chuỗi tại chỗ, thay đổi kích thước chuỗi đầu ra nếu cần.
Java có String, StringBuffer và StringBuilder:
Chuỗi: Bất biến của nó
StringBuffer: Có thể thay đổi và ThreadSafe của nó
StringBuilder: Có thể thay đổi nhưng không phải ThreadSafe, được giới thiệu trong Java 1.5
Chuỗi ví dụ:
public class T1 {
public static void main(String[] args){
String s = "Hello";
for (int i=0;i<10;i++) {
s = s+"a";
System.out.println(s);
}
}
}
}
đầu ra: 10 Chuỗi khác nhau sẽ được tạo thay vì chỉ 1 Chuỗi.
Helloa
Helloaa
Helloaaa
Helloaaaa
Helloaaaaa
Helloaaaaaa
Helloaaaaaaa
Helloaaaaaaaa
Helloaaaaaaaaa
Helloaaaaaaaaaa
Ví dụ: StringBuilder: Chỉ 1 đối tượng StringBuilder sẽ được tạo.
public class T1 {
public static void main(String[] args){
StringBuilder s = new StringBuilder("Hello");
for (int i=0;i<10;i++) {
s.append("a");
System.out.println(s);
}
}
}