1. So sánh tham chiếu và nội dung
Trong Java, chuỗi — là đối tượng chứ không phải kiểu nguyên thủy. Khi bạn khai báo biến a và b, chúng có thể trỏ tới cùng một chuỗi trong String Pool. Còn c, được tạo qua constructor, — là một đối tượng khác. Toán tử == so sánh tham chiếu, không phải nội dung.
String a = "hello";
String b = "hello";
String c = new String("hello");
System.out.println(a == b); // true (rất có thể là chuỗi đã intern)
System.out.println(a == c); // false (đối tượng khác nhau)
Minh họa lỗi
String s1 = "Java";
String s2 = new String("Java");
System.out.println(s1 == s2); // false
Mặc dù các chuỗi trông giống hệt nhau, chúng là các đối tượng khác nhau trong bộ nhớ.
2. equals(): so sánh nội dung chuỗi
Để so sánh đúng nội dung, hãy dùng phương thức equals() — nó so sánh từng ký tự (có phân biệt hoa thường).
String s1 = "Java";
String s2 = new String("Java");
System.out.println(s1.equals(s2)); // true
Ví dụ: so sánh mật khẩu
String inputPassword = "Secret123";
String realPassword = "Secret123";
if (inputPassword.equals(realPassword))
{
System.out.println("Truy cập được cấp!");
}
else
{
System.out.println("Mật khẩu không đúng.");
}
Quan trọng!
Nếu ít nhất một đối tượng là null, gọi equals() sẽ dẫn tới NullPointerException. Mẫu an toàn:
if ("cái gì đó".equals(someString)) { ... }
3. equalsIgnoreCase(): so sánh không phân biệt hoa thường
Khi cần bỏ qua phân biệt hoa thường (ví dụ, dữ liệu người dùng nhập), hãy dùng equalsIgnoreCase().
String name1 = "Ivan";
String name2 = "ivan";
System.out.println(name1.equalsIgnoreCase(name2)); // true
Ví dụ: so sánh địa chỉ email
String email1 = "User@Example.com";
String email2 = "user@example.com";
if (email1.equalsIgnoreCase(email2))
{
System.out.println("Email khớp nhau!");
}
Tóm tắt: equals vs equalsIgnoreCase
| Phương thức | Phân biệt hoa thường? | Ví dụ “Java” vs “java” |
|---|---|---|
|
Có | |
|
Không | |
4. compareTo(): so sánh chuỗi theo thứ tự từ điển
Phương thức compareTo() thực hiện so sánh theo thứ tự từ điển (lexicographic). Trả về số âm nếu chuỗi thứ nhất “nhỏ hơn”, 0 — bằng nhau, số dương — nếu “lớn hơn”.
System.out.println("apple".compareTo("banana")); // < 0
System.out.println("apple".compareTo("apple")); // 0
System.out.println("banana".compareTo("apple")); // > 0
a.compareTo(b) →
< 0 — nếu a đứng trước b
0 — nếu bằng nhau
> 0 — nếu a đứng sau b
compareTo()
Hoạt động như thế nào?
- So sánh diễn ra từ trái sang phải theo mã Unicode của ký tự.
- Tại điểm khác biệt đầu tiên, trả về hiệu của mã ký tự.
- Nếu một chuỗi là tiền tố của chuỗi kia, chuỗi ngắn hơn “nhỏ hơn”.
System.out.println("cat".compareTo("catalog")); // < 0 ("cat" ngắn hơn)
System.out.println("catalog".compareTo("cat")); // > 0
Ví dụ: sắp xếp mảng chuỗi
String[] fruits = {"banana", "apple", "pear"};
Arrays.sort(fruits); // bên trong dùng compareTo()
System.out.println(Arrays.toString(fruits)); // [apple, banana, pear]
compareToIgnoreCase()
System.out.println("Java".compareToIgnoreCase("java")); // 0
5. Các phương thức startsWith() và endsWith()
Các phương thức startsWith() và endsWith() kiểm tra phần đầu và phần cuối chuỗi, trả về true/false.
String fileName = "document.pdf";
String url = "https://www.google.com";
System.out.println(fileName.startsWith("doc")); // true
System.out.println(fileName.endsWith(".txt")); // false
System.out.println(url.startsWith("https://")); // true
Dùng để: xác thực định dạng (tên tệp, URL) và lọc theo tiền tố/hậu tố (ví dụ, tất cả ".jpg").
6. Phương thức contains(): tìm chuỗi con
contains(CharSequence s) — cách đơn giản để kiểm tra sự xuất hiện của chuỗi con. Có phân biệt hoa thường.
String text = "Chào mừng đến với thế giới Java!";
System.out.println(text.contains("thế giới")); // true
System.out.println(text.contains("C++")); // false
Để bỏ qua phân biệt hoa thường, chuyển cả hai chuỗi về cùng một dạng: toLowerCase()/toUpperCase().
7. Các phương thức toLowerCase() và toUpperCase()
Trả về một chuỗi mới đã được chuyển sang chữ thường hoặc chữ hoa. Hữu ích cho so sánh không phân biệt hoa thường và định dạng.
String title = "Java Programming";
String lower = title.toLowerCase();
String upper = title.toUpperCase();
System.out.println(lower); // java programming
System.out.println(upper); // JAVA PROGRAMMING
8. Phương thức split(): tách chuỗi thành các phần
split(String regex) tách chuỗi theo một delimiter (biểu thức chính quy) và trả về mảng String[].
Ví dụ 1: theo dấu phẩy
String names = "Alex,Maria,Ivan,Elena";
String[] nameArray = names.split(",");
for (String name : nameArray)
{
System.out.println(name.trim()); // trim() loại bỏ khoảng trắng có thể có
}
// Kết quả:
// Alex
// Maria
// Ivan
// Elena
Ví dụ 2: theo dấu cách
String sentence = "Tôi đang học Java";
String[] words = sentence.split(" ");
for (String word : words)
{
System.out.println(word);
}
// Kết quả:
// Tôi
// đang học
// Java
Lưu ý:
- Delimiter là regex. Cần escape ký tự đặc biệt (ví dụ, dấu chấm: "\\.").
- Phương thức luôn trả về mảng, kể cả khi chỉ có một phần tử.
9. Thực hành: so sánh chuỗi trong ứng dụng thực tế
String registeredEmail = "user@example.com";
String registeredPassword = "Secret123";
Scanner console = new Scanner(System.in);
System.out.print("Nhập email: ");
String email = console.nextLine();
System.out.print("Nhập mật khẩu: ");
String password = console.nextLine();
// So sánh email không phân biệt hoa thường, còn mật khẩu thì phân biệt
if (email.equalsIgnoreCase(registeredEmail) && password.equals(registeredPassword))
{
System.out.println("Chào mừng!");
}
else
{
System.out.println("Email hoặc mật khẩu không đúng.");
}
Ghi chú: đối với email dùng equalsIgnoreCase(), còn đối với mật khẩu — dùng nghiêm ngặt equals(). Không được dùng toán tử == cho chuỗi — nó so sánh tham chiếu.
10. Các lỗi thường gặp khi so sánh chuỗi
Lỗi №1: So sánh chuỗi bằng == thay vì equals()
Toán tử == so sánh tham chiếu chứ không phải nội dung, vì vậy kết quả có thể bất ngờ.
Lỗi №2: Gọi equals() trên đối tượng có thể là null
Hãy gọi phương thức trên đối tượng chắc chắn không-null hoặc dùng Objects.equals(a, b).
Lỗi №3: Bỏ qua phân biệt hoa thường khi điều đó quan trọng
Ví dụ, mật khẩu phải được so sánh có phân biệt hoa thường. Hãy làm rõ yêu cầu.
Lỗi №4: So sánh chuỗi với đối tượng kiểu khác
"123" và 123 — không giống nhau. equals() không tự động chuyển kiểu.
Lỗi №5: Sắp xếp chuỗi có lẫn hoa và thường
Chữ hoa đứng trước chữ thường. Để sắp xếp không phân biệt hoa thường, dùng Arrays.sort(array, String.CASE_INSENSITIVE_ORDER).
GO TO FULL VERSION