[JAVA] Sự khác biệt của StringBuilder, String concatenation
Với Java thật đơn giản để ghép các chuỗi kí tự lại với nhau, chỉ việc sử dụng toán tử ‘+’, nhưng vấn đề là liệu toán tử ‘+’ đó có phải là cách tốt nhất khi cần cộng nhiều chuỗi kí tự lại với nhau hay không và vì sao đã có toán tử ‘+’ đơn giản như vậy mà Java lại còn có StringBuilder cũng để nối các xâu kí tự. Trong bài viết này mình sẽ trả lời những câu hỏi đó, và cho các bạn thấy được vì sao trong các checker của Android Lint lại có checker khuyên các bạn sử dụng StringBuilder.append() thay cho ‘+’ (String concatenation).
Toán tử ‘+’ thì ai cũng biết rồi nhưng StringBuilder thì chưa hẳn là ai cũng biết, vì vậy mình sẽ giới thiệu sơ qua về StringBuilder một chút trước khi bắt đầu đi vào những ưu điểm của StringBuilder so với cách sử dụng toán tử ‘+’ thông thường.
StringBuilder
Đầu tiên, StringBuilder là kiểu dữ liệu có thể thay đổi (mutable) về độ dài và nội dung. Chúng ta chỉ cần tạo ra đối tượng kiểu StringBuilder, sau đó nối các nội dung tiếp theo vào đối tượng hiện tại mà không cần tạo mới đối tượng nào khác. Cụ thể để sử dụng StringBuilder bạn chỉ việc tạo 1 đối tượng kiểu StringBuilder như sau:
1 |
StringBuilder builder = new StringBuilder(); |
Và khi cần thêm 1 chuỗi vào sau của String Builder thì ta sử dụng phương thức append():
1 |
builder.append(“abc”); |
hoặc chèn vào 1 vị trí bắt kì ta sử dụng phương thức insert():
1 |
builder.insert(10 , “abc”); //chèn chuỗi “abc” vào vị trí thứ 10 trong StringBuilder |
thậm chí bạn còn có thể thay thế hoặc xóa một chuỗi nào đó trong StringBuilder thông qua các phương thức replace() và delete():
1 2 |
builder.replace(10, 13, “abc”); builder.delete(10, 13); |
Và để xuất ra chuỗi dạng String, ta chỉ cần sử dụng phương thức toString() của StringBuilder() là xong:
1 |
String str = builder.toString(); |
Tiếp theo, chúng ta sẽ xem xét một chút về mối quan hệ giữa String, StringBuilder thông qua sơ đồ thừa kế của chúng.
Từ sơ đồ ta có thể thấy, StringBuilder cũng thực thi (implements) giao diện CharSequence có giống String vì vậy nó cũng có các phương thức tương tự String, ngoài ra nó còn thực thi giao diện Appendable nên nó có vài phương thức khác với String, đó chính là phương thức append(), chính điều này đã tạo ra sự khác biệt cho StringBuilder so với String.
Sau khi đã tìm hiểu sơ qua về StringBuilder, bây giờ chúng ta sẽ đi trả lời câu hỏi đã nêu ra từ đầu.
Để trả lời câu hỏi này mình sẽ viết một đoạn code để thử nghiệm hiệu năng của String và StringBuilder. Đoạn code này các bạn có thể download tại đây.
Đoạn code này đơn giản chỉ là thực hiện gọi toán tử ‘+’ của String và phương thức append() của StringBuilder với số lần xác định là 1, 10, 100, 1000 và 10000, sau đó đo thời gian thực hiện của từng lần thực hiện. Để đảm bảo công bằng, với mỗi lần thực hiện mình sẽ lặp lại 10 lần và lấy trung bình. Kết quả được thể hiện tại bảng dưới đây:
Theo như kết quả ở trên, bạn có thể thấy nếu chỉ gọi 1 lần thì thời gian chênh lệch giữa String ‘+’ và StringBuilder append() cũng chẳng đáng là bao, tuy nhiên theo số lần gọi tăng lên thì thời gian chênh lệch cũng tăng theo, và tới 10000 lần gọi thì lúc này thời gian đã thực hiện (execution time) khi dùng String ‘+’ đã gấp append() của StringBuilder tới 225 lần, một con số khủng khiếp phải không nào.
Vâng qua ví dụ nhỏ ở trên hẳn là các bạn đã biết được vì sao Android Lint lại khuyên các bạn sử dụng StringBuilder thay cho String để tăng performance của ứng dụng rồi phải không nào. Nhưng một câu hỏi đặt ra là khi nào nên sử dụng StringBuilder thay cho String, chẳng lẽ cứ mỗi lần muốn nối 2 chuỗi, hay chỉ đơn giản là thêm 1 kí tự vào cuối chuỗi mà lại phải sử dụng StringBuilder với các thao tác lằng nhằng như khởi tạo (bằng cách gọi toán tử new) rồi dùng append, sau đó lại gọi toString sao? Nếu làm như vậy thì rất nhiều đoạn code sẽ trở nên khó hiểu và rối rắm, và dĩ nhiên chúng ta cũng không muốn đánh đổi điều này trừ khi hiệu năng phải được cải thiện đáng kể.
Vậy khi nào thì nên sử dụng StringBuilder? Câu trả lời là bạn chỉ nên sử dụng StringBuilder, khi bạn muốn nối chuỗi bằng cách sử dụng vòng lặp mà thôi.
Ví dụ khi bạn định tạo 1 chuỗi chứa các số từ 1 đến 100 liên tiếp nhau, thì các bạn nên sử dụng cách sau thay cho việc sử dụng String như bình thường:
– Và hãy nhớ là nếu đã sử dụng StringBuilder thì đừng có sử dụng ‘+’ ở bên trong nữa nhé. Mình đã từng thấy khá nhiều trường hợp khá hài hước tương tự như sau:
1 |
builder.append(“abc”+”def”); |
thay cho việc sử dụng chuẩn là:
1 |
builder.append(“abc”).append(“def”); |
Thật là buồn cười đúng không nào 😆
Vâng mình xin được phép kết thúc bài viết này ở đây, hi vọng bài viết của mình sẽ có ích cho các bạn.
- Google+
- Wordpress