字符串比较
字符串比较是开发中最常见的操作之一。
equals内容比较
equals比较字符串内容
Java
String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
String s4 = "World";
// equals比较内容是否相同
boolean r1 = s1.equals(s2); // true
boolean r2 = s1.equals(s3); // true
boolean r3 = s1.equals(s4); // false
// equals区分大小写
String s5 = "hello";
boolean r4 = s1.equals(s5); // false
equalsIgnoreCase忽略大小写
Java
String s1 = "Hello";
String s2 = "hello";
// equalsIgnoreCase忽略大小写比较
boolean r1 = s1.equalsIgnoreCase(s2); // true
String s3 = "HELLO";
boolean r2 = s1.equalsIgnoreCase(s3); // true
安全调用equals
Java
// 错误方式:null调用equals会NPE
String str = null;
// str.equals("Hello"); // NullPointerException
// 正确方式1:常量在前
boolean r = "Hello".equals(str); // false(安全)
// 正确方式2:null检查
if (str != null && str.equals("Hello")) {
// 处理
}
// 正确方式3:Objects.equals(Java 7+)
boolean r = Objects.equals(str, "Hello"); // false(空安全)
==引用比较
==比较引用地址
Java
String s1 = "Hello"; // 常量池
String s2 = "Hello"; // 常量池(同一对象)
String s3 = new String("Hello"); // 堆内存(新对象)
// ==比较是否同一对象(地址)
boolean r1 = s1 == s2; // true(同一常量池对象)
boolean r2 = s1 == s3; // false(不同对象)
boolean r3 = s2 == s3; // false
字面量与new的区别
Java
// 字面量:常量池,相同内容共享同一对象
String a1 = "Java";
String a2 = "Java";
System.out.println(a1 == a2); // true
// new:堆内存,每次创建新对象
String b1 = new String("Java");
String b2 = new String("Java");
System.out.println(b1 == b2); // false
// 内容相同
System.out.println(a1.equals(b1)); // true
intern返回常量池引用
Java
String s1 = new String("Hello");
String s2 = s1.intern(); // 返回常量池引用
String s3 = "Hello"; // 常量池
System.out.println(s2 == s3); // true
compareTo字典序比较
compareTo比较字典顺序
Java
String s1 = "Apple";
String s2 = "Banana";
String s3 = "Apple";
// 返回值:
// 0:相等
// < 0:s1在s2之前(字典序)
// > 0:s1在s2之后
int r1 = s1.compareTo(s2); // -1(Apple < Banana)
int r2 = s2.compareTo(s1); // 1(Banana > Apple)
int r3 = s1.compareTo(s3); // 0(相等)
compareTo比较原理
Java
// 按字符逐个比较
"Apple".compareTo("Apricot");
// A相同,p相同,p < r → 返回负数
// 长度不同时
"App".compareTo("Apple");
// 前三个字符相同,前者短 → 返回负数
compareToIgnoreCase忽略大小写
Java
String s1 = "Apple";
String s2 = "apple";
int r1 = s1.compareTo(s2); // 负数(区分大小写)
int r2 = s1.compareToIgnoreCase(s2); // 0(忽略大小写)
字符串排序
使用compareTo排序
Java
String[] arr = {"Banana", "Apple", "Cherry"};
Arrays.sort(arr); // 自动使用compareTo
// 结果:["Apple", "Banana", "Cherry"]
// 手动排序
List<String> list = Arrays.asList("Banana", "Apple", "Cherry");
list.sort(String::compareTo); // 同样效果
自定义比较器
Java
String[] arr = {"Banana", "Apple", "Cherry"};
// 按长度排序
Arrays.sort(arr, (a, b) -> a.length() - b.length());
// ["Apple", "Banana", "Cherry"](按长度5,6,6)
// 忽略大小写排序
Arrays.sort(arr, String::compareToIgnoreCase);
常量池与比较
编译期确定的字符串
Java
// 编译期确定,进入常量池
String s1 = "Hello";
String s2 = "Hel" + "lo"; // 编译期合并
System.out.println(s1 == s2); // true
// 运行期拼接,不进常量池
String s3 = "Hel";
String s4 = s3 + "lo"; // 运行期拼接
System.out.println(s1 == s4); // false
intern显式加入常量池
Java
String s1 = new String("Hello");
String s2 = s1.intern(); // 加入常量池
String s3 = "Hello";
System.out.println(s2 == s3); // true(同一常量池对象)
比较方法对比
equals与==对比
| 方法 | 比较内容 | 适用场景 |
|---|---|---|
| equals | 字符串内容是否相同 | 业务逻辑比较 |
| == | 是否同一对象(地址) | 极少使用,常量池判断 |
Java
// 业务比较用equals
if (input.equals("yes")) {
// 用户输入yes
}
// ==仅用于常量池判断(不推荐日常使用)
String s1 = "Java";
String s2 = "Java";
if (s1 == s2) {
// 常量池同一对象
}
各比较方法总结
| 方法 | 作用 | 返回值 |
|---|---|---|
| equals() | 内容相等判断 | boolean |
| equalsIgnoreCase() | 忽略大小写相等 | boolean |
| == | 同一对象判断 | boolean |
| compareTo() | 字典序比较 | int(0/负/正) |
| compareToIgnoreCase() | 忽略大小写字典序 | int |
空值安全比较
null处理
Java
String s1 = null;
String s2 = "Hello";
// 错误:null调用equals
// s1.equals(s2); // NullPointerException
// 正确方式1:常量在前
boolean r = "Hello".equals(s1); // false
// 正确方式2:Objects.equals
boolean r2 = Objects.equals(s1, s2); // false
// 正确方式3:StringUtils(Apache Commons)
boolean r3 = StringUtils.equals(s1, s2); // false
比较最佳实践
内容比较用equals
Java
// 推荐:equals比较内容
String input = getUserInput();
if ("yes".equals(input)) {
// 安全,即使input为null
}
// 不推荐:==比较地址
if (input == "yes") { // 可能失败
// 即使内容相同,可能不是同一对象
}
大小写不敏感比较
Java
String input = "YES";
// 使用equalsIgnoreCase
if ("yes".equalsIgnoreCase(input)) {
// 匹配YES、yes、Yes等
}
多条件比较
Java
String input = "quit";
// 多值判断
if ("quit".equals(input) || "exit".equals(input) || "q".equals(input)) {
// 退出
}
// 使用contains(List)
List<String> exits = Arrays.asList("quit", "exit", "q");
if (exits.contains(input)) {
// 退出
}
要点总结
- equals()比较字符串内容是否相同
- equalsIgnoreCase()忽略大小写比较
- ==比较是否同一对象(引用地址)
- 字面量相同内容共享常量池对象
- new创建的对象不共享常量池
- compareTo()字典序比较,返回0/负/正
- compareToIgnoreCase()忽略大小写字典序
- 常量在前调用equals避免NPE
- Objects.equals()空安全比较
- intern()返回常量池引用
- 业务比较使用equals,不用==
- 字符串排序使用compareTo
📝 发现内容有误?点击此处直接编辑