Java String compareToIgnoreCase() 比较两个字符串相等

Java 程序不区分大小写比较两个字符串。请注意compareTo()compareToIgnoreCase()方法的行为方式相同,只是后者不区分大小写。

compareToIgnoreCase() 在将每个字符转换为 unicode 值之后,对两个字符串逐个字符地进行比较。

字符串 compareToIgnoreCase() 方法

在 Java 源代码中,String 的 compareToIgnoreCase() 方法如下:

public int compare(String s1, String s2) {
    int n1 = s1.length();
    int n2 = s2.length();
    int min = Math.min(n1, n2);
    for (int i = 0; i < min; i++) {
        char c1 = s1.charAt(i);
        char c2 = s2.charAt(i);
        if (c1 != c2) {
            c1 = Character.toUpperCase(c1);
            c2 = Character.toUpperCase(c2);
            if (c1 != c2) {
                c1 = Character.toLowerCase(c1);
                c2 = Character.toLowerCase(c2);
                if (c1 != c2) {
                    // No overflow because of numeric promotion
                    return c1 - c2;
                }
            }
        }
    }
    return n1 - n2;
}

compareTo() 方法相比,compareToIgnoreCase() 方法是只是对字符进行了转换为大写比较,再转换为小写比较。

这里的对比算法有点迷惑,为啥先转为大写相比,又转为小写相比较?我们先用下面这个例子来演示一个场景。

大小写转换

下面的代码是将字典中前 350 个字符进行大小写转换然后,找出的,大写相同而小写不同的字符。

public class StringUpperLowerCase {
    public static void main(String[] args) {
        int times = 350;
        for (int i = 0; i < times; i++) {
            char ch = (char) i;
            for (int j = 0; j < times; j++) {
                if (i != j) {
                    char ch2 = (char) j;
                    if (ch2 != ch) {
                        boolean b1 = Character.toUpperCase(ch) == Character.toUpperCase(ch2);
                        boolean b2 = Character.toLowerCase(ch) == Character.toLowerCase(ch2);
                        if (b1 && !b2) {
                            System.out.print("大写相同: " + i + " and " + j + ", ");
                            System.out.println("Ch1=" + ch + " Ch2=" + ch2);
                        } else if (b2 && !b1) {
                            System.out.print("小写相同: " + i + " and " + j + ", ");
                            System.out.println("Ch1=" + ch + " Ch2=" + ch2);
                        }
                    }
                }
            }
        }
    }
}
小写相同: 73 and 304, Ch1=I Ch2=İ
大写相同: 73 and 305, Ch1=I Ch2=ı
小写相同: 105 and 304, Ch1=i Ch2=İ
大写相同: 105 and 305, Ch1=i Ch2=ı
小写相同: 304 and 73, Ch1=İ Ch2=I
小写相同: 304 and 105, Ch1=İ Ch2=i
大写相同: 305 and 73, Ch1=ı Ch2=I
大写相同: 305 and 105, Ch1=ı Ch2=i
执行结果

实际上,上述字符都是非英语环境的。在德语、希腊语等西欧语种中,大小写不是 1:1 存在的,某些字符它们的多个小写字符对应同一个大写字符。

compareToIgnoreCase() 示例

public class StringCompareIgnoreCase {

    public static void main(String[] args) {
        System.out.println("Hello".compareTo("hello"));// -32
        System.out.println("Hello".compareToIgnoreCase("hello")); // 0
        System.out.println("Hello".compareToIgnoreCase("frank")); // 2
        System.out.println("Hello".compareToIgnoreCase("frank")); // 2
        System.out.println("Hello".compareToIgnoreCase("Icy")); // -1
        System.out.println("Hello".compareToIgnoreCase(null)); //java.lang.NullPointerException
    }
}

compareToIgnoreCase() 仅仅是忽略大小写的比较两个字符串,其用法与 compareTo() 完全一致。

-32
0
2
2
-1
执行结果

compareToIgnoreCase() 与 equalsIgnoreCase()

为什么把他两拉出来,因此它们都能判断两个字符串是否相等。

  • compareToIgnoreCase() 根据字典顺序比较两个字符串大小
  • equalsIgnoreCase() 要考虑更多的维度,如字符串地址、长度等,理论上速度比较速度更快
  • compareToIgnoreCase() 返回的是第一个不相等字符的偏差,为整数
  • equalsIgnoreCase() 返回两个字符串是否相等,为布尔值
  • equalsIgnoreCase() 对于 null 返回 false,compareToIgnoreCase() 不能处理 null,会抛出空指针异常

compareToIgnoreCase() 返回的是两个字符串的偏移量,但是这在业务角度往往是无意义的。我们一般只关注两个字符串是不是相等,而不是它们的差值,因此 equalsIgnoreCase() 更有业务价值。

标签: