在 Java 中,比较字符串的大小主要有三种方式,它们各有不同的用途和原理:

(图片来源网络,侵删)
equals()和equalsIgnoreCase():内容比较,判断两个字符串的字符序列是否完全相同。compareTo()和compareToIgnoreCase():字典序比较,基于 Unicode 值逐个字符比较,不仅能判断大小,还能确定顺序。- (等于号):引用比较,判断两个字符串变量是否指向内存中的同一个对象。
内容比较:equals() 和 equalsIgnoreCase()
这是最常用、最安全的比较方式,用于判断两个字符串的内容是否相等。
equals()
- 功能:比较两个字符串的内容是否完全一致(区分大小写)。
- 返回值:
true:如果两个字符串长度相同,且对应位置的字符都相同。false:否则。
示例代码:
String str1 = "Hello";
String str2 = "Hello";
String str3 = "hello";
String str4 = new String("Hello"); // new 关键字会创建一个新的字符串对象
相同,区分大小写
System.out.println(str1.equals(str2)); // 输出: true
System.out.println(str1.equals(str3)); // 输出: false (因为 'H' 和 'h' 不同)
System.out.println(str1.equals(str4)); // 输出: true (内容相同,都是 "Hello")
// 推荐:常量放前面,避免 NullPointerException
"".equals(someString); // someString 是 null,这里返回 false,不会报错
someString.equals(""); // someString 是 null,这里会抛出 NullPointerException
equalsIgnoreCase()
- 功能:与
equals()类似,但在比较时忽略大小写。 - 返回值:
true:如果两个字符串长度相同,且对应位置的字符在忽略大小写的情况下都相同。false:否则。
示例代码:
String str1 = "Hello";
String str3 = "hello";
System.out.println(str1.equalsIgnoreCase(str3)); // 输出: true
System.out.println("Java".equalsIgnoreCase("java")); // 输出: true
字典序比较:compareTo() 和 compareToIgnoreCase()
compareTo() 方法用于按字典顺序(lexicographical order)比较两个字符串,它返回一个整数值,告诉你第一个字符串是小于、等于还是大于第二个字符串。

(图片来源网络,侵删)
compareTo()
- 功能:基于字符的 Unicode 值进行逐个比较。
- 返回值:
- 负整数:表示调用该方法的字符串(
this)小于参数字符串。 - 零 (
0):表示两个字符串相等。 - 正整数:表示调用该方法的字符串(
this)大于参数字符串。
- 负整数:表示调用该方法的字符串(
比较规则:
- 从左到右,逐个比较对应字符的 Unicode 码点。
- 如果在某个位置发现不同,则这两个字符的 Unicode 码点之差就是返回值。
- 如果所有字符都相同,但一个字符串比另一个长,则较长的字符串更大,返回值为长度之差。
示例代码:
String s1 = "apple";
String s2 = "banana";
String s3 = "apple";
String s4 = "apples";
String s5 = "Apple"; // 'A' 的 Unicode 值小于 'a'
System.out.println(s1.compareTo(s2)); // 输出: 负数 (因为 'a' < 'b')
System.out.println(s2.compareTo(s1)); // 输出: 正数 (因为 'b' > 'a')
System.out.println(s1.compareTo(s3)); // 输出: 0 (完全相同)
System.out.println(s1.compareTo(s4)); // 输出: 负数 ("apple" 比 "apples" 短)
System.out.println(s1.compareTo(s5)); // 输出: 正数 ('a' > 'A')
实际应用:排序
compareTo() 是实现字符串排序的关键,例如对 List<String> 进行排序:

(图片来源网络,侵删)
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
List<String> fruits = new ArrayList<>();
fruits.add("Orange");
fruits.add("Apple");
fruits.add("Banana");
System.out.println("排序前: " + fruits);
Collections.sort(fruits); // 内部就是使用 compareTo() 进行比较
System.out.println("排序后: " + fruits);
// 输出:
// 排序前: [Orange, Apple, Banana]
// 排序后: [Apple, Banana, Orange]
compareToIgnoreCase()
- 功能:与
compareTo()相同,但在比较时忽略大小写。 - 返回值:同
compareTo()。
示例代码:
String s1 = "apple"; String s5 = "Apple"; System.out.println(s1.compareTo(s5)); // 输出: 正数 (因为 'a' > 'A') System.out.println(s1.compareToIgnoreCase(s5)); // 输出: 0 (忽略大小写后相等)
引用比较: (等于号)
这是初学者最容易混淆的地方!
比较的不是字符串的“内容”,而是两个变量是否指向内存中的同一个对象(即同一个内存地址)。
- 功能:比较两个对象的引用地址。
- 返回值:
true:两个变量指向同一个对象。false:两个变量指向不同的对象。
示例代码:
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
// s1 和 s2 都指向字符串常量池中的 "hello" 对象
System.out.println(s1 == s2); // 输出: true
// s3 是通过 new 关键字创建的新对象,它有自己的内存地址
System.out.println(s1 == s3); // 输出: false
相同,但它们是两个独立的对象
System.out.println(s1.equals(s3)); // 输出: true (内容比较)
为什么会出现这种情况? Java 为了提高性能,会使用一个叫做 字符串常量池 (String Pool) 的区域。
- 当你使用
String s = "hello";这种方式时,JVM 会先在常量池中查找是否存在 "hello",如果存在则直接引用,如果不存在则创建并放入池中。 - 当你使用
new String("hello")时,JVM 一定会在堆内存中创建一个新的字符串对象,即使池中已经存在 "hello"。
总结与最佳实践
| 方法 | 比较类型 | 区分大小写 | 主要用途 | 返回值 |
|---|---|---|---|---|
equals() |
内容比较 | 是 | 判断两个字符串内容是否相等 | boolean |
equalsIgnoreCase() |
内容比较 | 否 | 判断两个字符串内容是否相等(忽略大小写) | boolean |
compareTo() |
字典序比较 | 是 | 排序、确定字符串的相对顺序 | int (负/零/正) |
compareToIgnoreCase() |
字典序比较 | 否 | 排序、确定字符串的相对顺序(忽略大小写) | int (负/零/正) |
| 引用比较 | - | 判断两个变量是否指向同一个对象 | boolean |
如何选择?
-
只想知道内容是否一样?
- 区分大小写:使用
str1.equals(str2)。 - 不区分大小写:使用
str1.equalsIgnoreCase(str2)。 - 永远不要用 来比较字符串内容!
- 区分大小写:使用
-
需要对字符串进行排序或判断大小顺序?
- 区分大小写:使用
str1.compareTo(str2)。 - 不区分大小写:使用
str1.compareToIgnoreCase(str2)。
- 区分大小写:使用
-
什么时候用 比较字符串?
- 几乎没有业务场景需要用到。
- 一个典型的场景是性能优化:当你确定两个字符串变量必须指向同一个对象时(从一个缓存中获取),可以用 来快速判断,因为它比
equals()更快(直接比较地址,不用逐个字符比较),但这属于高级优化技巧,初学者应避免。
记住黄金法则:
比较字符串内容,用
equals();比较字符串顺序,用compareTo();比较对象引用,用 。
