Làm cách nào để làm cho chuỗi so sánh của tôi không phân biệt chữ hoa chữ thường?


111

Tôi đã tạo một chương trình Java để so sánh hai chuỗi:

String s1 = "Hello";
String s2 = "hello";

if (s1.equals(s2)) {
    System.out.println("hai");
} else {
    System.out.println("welcome");
}

Nó hiển thị "chào mừng". Tôi hiểu nó phân biệt chữ hoa chữ thường. Nhưng vấn đề của tôi là tôi muốn so sánh hai chuỗi mà không có phân biệt chữ hoa chữ thường. Tức là tôi mong đợi đầu ra là hai.


3
Nếu bạn biết nó phân biệt chữ hoa chữ thường, bạn có thể chuyển đổi cả hai thành chữ thường hoặc chữ hoa trước khi so sánh.
fastcodejava

nếu bạn sử dụng, s1.equalsIgnoreCase(s2)bạn có thể không thực hiện được ở mọi nơi cần hoàn thành. Tôi khuyên bạn nên tìm chuỗi đến từ đâu - có lẽ là tệp hoặc cơ sở dữ liệu hoặc thông tin người dùng nhập - và chuyển đổi thành chữ hoa (hoặc chữ thường) và tiếp tục sử dụng .equals để so sánh.
H2ONaCl

2
Không chuyển đổi thành chữ thường / hoa (như đề xuất của các nhận xét ở trên), hãy sử dụng equalsIgnoreCasephương pháp được chấp nhận . Đọc về vấn đề tiếng Thổ Nhĩ Kỳ I và các vấn đề Unicode tương tự để biết cơ sở.
Ohad Schneider

1
@OhadSchneider vẫn equalsIgnoreCasetrả về giá trị sai cho tiếng Thổ Nhĩ Kỳ, vì nó trả về true khi so sánh "i" và "I", mặc dù nó phải trả về false. Vì vậy, tôi nghi ngờ rằng nếu bạn muốn xem xét ngôn ngữ, a Collatorthực sự là một cách để đi.
Trejkaz

1
@OhadSchneider Tôi tự hỏi. Nó nói rằng thực hiện trên mỗi ký tự sẽ tạo ra cùng một kết quả, nhưng thực hiện toLowerCase/ toUpperCasetrên toàn bộ chuỗi và thực hiện trên mỗi ký tự cũng cho hai kết quả khác nhau.
Trejkaz

Câu trả lời:


171
  • Tốt nhất nên sử dụng s1.equalsIgnoreCase(s2): (xem javadoc )
  • Bạn cũng có thể chuyển đổi cả hai thành chữ hoa / thường và sử dụng s1.equals(s2)

39
Chỉ cần lưu ý rằng hai giải pháp không nhất thiết phải giống nhau cho tất cả các ngôn ngữ. String # equalsIgnoreCase không sử dụng quy tắc viết hoa cụ thể theo ngôn ngữ, trong khi String # toLowerCase và #toUpperCase thì có.
jarnbjo

1
@jarnbjo Bạn có thể cho ví dụ về sự khác biệt đó không?
towi

16
Các quy tắc trường hợp cụ thể theo ngôn ngữ ít nhất được triển khai cho tiếng Thổ Nhĩ Kỳ và tiếng Đức. Tiếng Thổ Nhĩ Kỳ coi I có và không có dấu chấm là hai chữ cái khác nhau, tạo ra các cặp chữ thường / hoa iİ và ıI trong khi các ngôn ngữ khác coi iI là một cặp và không sử dụng các chữ cái ı và İ. Trong tiếng Đức, chữ thường ß được viết hoa là "SS".
jarnbjo


24

String.equalsIgnoreCase là lựa chọn thực tế nhất để so sánh chuỗi không phân biệt chữ hoa chữ thường.

Tuy nhiên, cần lưu ý rằng phương pháp này không gấp hay phân rã toàn bộ chữ hoa chữ thường và do đó không thể thực hiện đối sánh vô cấp như được chỉ định trong tiêu chuẩn Unicode. Trên thực tế, các API JDK không cung cấp quyền truy cập vào thông tin về dữ liệu ký tự gấp chữ hoa, vì vậy công việc này tốt nhất nên được ủy quyền cho thư viện bên thứ ba đã được thử và kiểm tra.

Thư viện đó là ICU , và đây là cách người ta có thể triển khai một tiện ích để so sánh chuỗi phân biệt chữ hoa chữ thường:

import com.ibm.icu.text.Normalizer2;

// ...

public static boolean equalsIgnoreCase(CharSequence s, CharSequence t) {
    Normalizer2 normalizer = Normalizer2.getNFKCCasefoldInstance();
    return normalizer.normalize(s).equals(normalizer.normalize(t));
}
    String brook = "flu\u0308ßchen";
    String BROOK = "FLÜSSCHEN";

    assert equalsIgnoreCase(brook, BROOK);

So sánh ngây thơ với String.equalsIgnoreCase, hoặc String.equalstrên chuỗi viết hoa hoặc viết thường sẽ không thành công ngay cả thử nghiệm đơn giản này.

(Xin lưu ý rằng kiểu gấp chữ hoa được xác định trước không phụ thuộc vào getNFKCCasefoldInstancengôn ngữ; đối với ngôn ngữ Thổ Nhĩ Kỳ, UCharacter.foldCasecó thể cần thêm một chút công việc liên quan ).


22

Bạn phải sử dụng compareToIgnoreCasephương thức của Stringđối tượng.

int compareValue = str1.compareToIgnoreCase(str2);

if (compareValue == 0)nó có nghĩa là str1bằng str2.


10
import java.lang.String; //contains equalsIgnoreCase()
/*
*
*/
String s1 = "Hello";
String s2 = "hello";

if (s1.equalsIgnoreCase(s2)) {
System.out.println("hai");
} else {
System.out.println("welcome");
}

Bây giờ nó sẽ xuất ra: hai


5

Trong API Java mặc định, bạn có:

String.CASE_INSENSITIVE_ORDER

Vì vậy, bạn không cần phải viết lại một trình so sánh nếu bạn sử dụng các chuỗi có cấu trúc dữ liệu Đã sắp xếp.

String s = "some text here";
s.equalsIgnoreCase("Some text here");

Là những gì bạn muốn để kiểm tra bình đẳng thuần túy trong mã của riêng bạn.

Chỉ để thông tin thêm về bất cứ điều gì liên quan đến sự bình đẳng của các chuỗi trong Java. Hàm hashCode () của lớp java.lang.String "phân biệt chữ hoa chữ thường":

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

Vì vậy, nếu bạn muốn sử dụng Hashtable / HashMap với Strings làm khóa và có các khóa như "SomeKey", "SOMEKEY" và "somekey" được coi là bằng nhau, thì bạn sẽ phải bọc chuỗi của mình trong một lớp khác (bạn không thể mở rộng Chuỗi vì nó là một lớp cuối cùng). Ví dụ :

private static class HashWrap {
    private final String value;
    private final int hash;

    public String get() {
        return value;
    }

    private HashWrap(String value) {
        this.value = value;
        String lc = value.toLowerCase();
        this.hash = lc.hashCode();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o instanceof HashWrap) {
            HashWrap that = (HashWrap) o;
            return value.equalsIgnoreCase(that.value);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return this.hash;
    }
}

và sau đó sử dụng nó như sau:

HashMap<HashWrap, Object> map = new HashMap<HashWrap, Object>();

2

Lưu ý rằng bạn cũng có thể muốn thực hiện kiểm tra null trước khi thực hiện .equals hoặc .equalsIgnoreCase của mình.

Một đối tượng String null không thể gọi một phương thức bằng.

I E:

public boolean areStringsSame(String str1, String str2)
{
    if (str1 == null && str2 == null)
        return true;
    if (str1 == null || str2 == null)
        return false;

    return str1.equalsIgnoreCase(str2);
}

1
Lưu ý: thứ hai hai báo cáo có thể được kết hợp để tạo ra cùng một kết quả như thế này: if (str1 == null || str2 == null) return false;.
LuckyMe

Mã sửa đổi để được sạch theo bình luận ở trên - là ngày dài :)
VeenarM

1
Bạn cũng có thể thay đổi dòng đầu tiên if (str1 == str2) return true;mà cả hai đều phục vụ cho null và cũng có thể sử dụng phím tắt trong trường hợp hai tham chiếu chuỗi tham chiếu đến cùng một đối tượng chuỗi.
Barney




1

Để trở thành nullsafe, bạn có thể sử dụng

org.apache.commons.lang.StringUtils.equalsIgnoreCase(String, String)

hoặc là

org.apache.commons.lang3.StringUtils.equalsIgnoreCase(CharSequence, CharSequence)

-6
public boolean newEquals(String str1, String str2)
{
    int len = str1.length();
int len1 = str2.length();
if(len==len1)
{
    for(int i=0,j=0;i<str1.length();i++,j++)
    {
        if(str1.charAt(i)!=str2.charAt(j))
        return false;
    }`enter code here`
}
return true;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.