So Sánh String, StringBuilder và StringBuffer

So Sánh String, StringBuilder và StringBuffer

Trong Java, String, StringBuilderStringBuffer đều được sử dụng để làm việc với chuỗi dữ liệu. Dưới đây là một so sánh chi tiết về tính hiệu quả và sử dụng trong các tình huống khác nhau của ba kiểu này.

I. String

String trong Java là một kiểu dữ liệu không thể sửa đổi (immutable), mỗi khi thực hiện thao tác như nối chuỗi, sẽ tạo ra một đối tượng chuỗi mới.

				
					public class ImmutableStringExample {
    public static void main(String[] args) {
        String str1 = "Hello"; // Tạo một đối tượng chuỗi

        // Thực hiện thêm vào chuỗi, tạo ra một đối tượng mới
        String str2 = str1.concat(" World");

        // In ra giá trị của str1 và str2
        System.out.println("str1: " + str1); // Kết quả: Hello
        System.out.println("str2: " + str2); // Kết quả: Hello World

        // Kiểm tra xem str1 có thay đổi không
        System.out.println("str1 after concat: " + str1); // Kết quả: Hello
    }
}

				
			

Trong ví dụ này, khi thực hiện phép nối chuỗi (concat), một đối tượng chuỗi mới được tạo ra cho str2. Đối tượng chuỗi ban đầu với str1 không bị thay đổi, và str1 vẫn giữ giá trị ban đầu của nó, chứng minh tính không thể sửa đổi của chuỗi String trong Java.

II. StringBuilder và StringBuffer

StringBuilderStringBuffer đều là kiểu dữ liệu có thể sửa đổi (mutable), cho phép thay đổi chuỗi mà không tạo ra đối tượng mới.

StringBuilder:

StringBuilder là một lớp không đồng bộ (non-synchronized), nhanh hơn StringBuffer nhưng không an toàn trong môi trường đa luồng.

				
					public class StringBuilderExample {
    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder("Hello"); // Tạo một đối tượng StringBuilder

        stringBuilder.append(" World"); // Thêm vào chuỗi, không tạo ra đối tượng mới

        System.out.println("Result: " + stringBuilder); // Kết quả: Hello World
    }
}

				
			

Trong ví dụ này, phương thức append được sử dụng để thêm chuỗi ” World” vào đối tượng StringBuilder stringBuilder. Đối tượng StringBuilder ban đầu được sửa đổi và không tạo ra một đối tượng mới khi thực hiện thao tác.

StringBuffer:
StringBuffer là một lớp đồng bộ (synchronized), an toàn trong môi trường đa luồng, tuy nhiên chậm hơn StringBuilder do việc đồng bộ hóa.

				
					public class StringBufferExample {
    public static void main(String[] args) {
        StringBuffer stringBuffer = new StringBuffer("Hello"); // Tạo một đối tượng StringBuffer

        stringBuffer.append(" World"); // Thêm vào chuỗi, không tạo ra đối tượng mới

        System.out.println("Result: " + stringBuffer); // Kết quả: Hello World
    }
}

				
			

Tương tự như StringBuilder, phương thức append cũng được sử dụng để thêm chuỗi ” World” vào đối tượng StringBuffer stringBuffer. Đối tượng StringBuffer ban đầu cũng được sửa đổi và không tạo ra một đối tượng mới khi thực hiện thao tác.

III. So Sánh Giữa Các Kiểu

  • Hiệu Suất: StringBuilder có hiệu suất cao nhất, tiếp theo là StringBuffer, và String có hiệu suất thấp nhất do tạo ra đối tượng mới mỗi khi thay đổi.

  • Đa Luồng: StringBuffer an toàn trong môi trường đa luồng, trong khi StringBuilder không an toàn.

				
					public class StringVsStringBuilderVsStringBuffer {
    public static void main(String[] args) {
        int iterations = 100000;
        long startTime, endTime;

        // String
        startTime = System.currentTimeMillis();
        String str = "";
        for (int i = 0; i < iterations; i++) {
            str += "hello";
        }
        endTime = System.currentTimeMillis();
        System.out.println("Time taken by String: " + (endTime - startTime) + "ms");

        // StringBuilder
        startTime = System.currentTimeMillis();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < iterations; i++) {
            stringBuilder.append("hello");
        }
        endTime = System.currentTimeMillis();
        System.out.println("Time taken by StringBuilder: " + (endTime - startTime) + "ms");

        // StringBuffer
        startTime = System.currentTimeMillis();
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < iterations; i++) {
            stringBuffer.append("hello");
        }
        endTime = System.currentTimeMillis();
        System.out.println("Time taken by StringBuffer: " + (endTime - startTime) + "ms");
    }
}

				
			

Kết quả:

				
					Time taken by String: 10640ms
Time taken by StringBuilder: 10ms
Time taken by StringBuffer: 22ms

				
			

IV. Lưu Ý

  • Sử dụng String khi không cần thay đổi dữ liệu chuỗi.
  • Sử dụng StringBuilder cho hiệu suất cao khi không cần đồng bộ.
  • Sử dụng StringBuffer cho độ an toàn trong môi trường đa luồng.

Việc lựa chọn giữa String, StringBuilderStringBuffer tùy thuộc vào yêu cầu của ứng dụng, với mục tiêu tối ưu hiệu suất xử lý chuỗi dữ liệu trong Java.