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
大写相同: 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
0
2
2
-1
compareToIgnoreCase() 与 equalsIgnoreCase()
为什么把他两拉出来,因此它们都能判断两个字符串是否相等。
- compareToIgnoreCase() 根据字典顺序比较两个字符串大小
- equalsIgnoreCase() 要考虑更多的维度,如字符串地址、长度等,理论上速度比较速度更快
- compareToIgnoreCase() 返回的是第一个不相等字符的偏差,为整数
- equalsIgnoreCase() 返回两个字符串是否相等,为布尔值
- equalsIgnoreCase() 对于 null 返回 false,compareToIgnoreCase() 不能处理 null,会抛出空指针异常
compareToIgnoreCase()
返回的是两个字符串的偏移量
,但是这在业务角度往往是无意义的。我们一般只关注两个字符串是不是相等,而不是它们的差值,因此 equalsIgnoreCase()
更有业务价值。