杰瑞科技汇

Java字符串大小比较,用equals还是==?

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

Java字符串大小比较,用equals还是==?-图1
(图片来源网络,侵删)
  1. equals()equalsIgnoreCase()内容比较,判断两个字符串的字符序列是否完全相同。
  2. compareTo()compareToIgnoreCase()字典序比较,基于 Unicode 值逐个字符比较,不仅能判断大小,还能确定顺序。
  3. (等于号)引用比较,判断两个字符串变量是否指向内存中的同一个对象。

内容比较: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)比较两个字符串,它返回一个整数值,告诉你第一个字符串是小于、等于还是大于第二个字符串。

Java字符串大小比较,用equals还是==?-图2
(图片来源网络,侵删)

compareTo()

  • 功能:基于字符的 Unicode 值进行逐个比较。
  • 返回值
    • 负整数:表示调用该方法的字符串(this小于参数字符串。
    • 零 (0):表示两个字符串相等
    • 正整数:表示调用该方法的字符串(this大于参数字符串。

比较规则:

  1. 从左到右,逐个比较对应字符的 Unicode 码点。
  2. 如果在某个位置发现不同,则这两个字符的 Unicode 码点之差就是返回值。
  3. 如果所有字符都相同,但一个字符串比另一个长,则较长的字符串更大,返回值为长度之差。

示例代码:

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> 进行排序:

Java字符串大小比较,用equals还是==?-图3
(图片来源网络,侵删)
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

如何选择?

  1. 只想知道内容是否一样?

    • 区分大小写:使用 str1.equals(str2)
    • 不区分大小写:使用 str1.equalsIgnoreCase(str2)
    • 永远不要用 来比较字符串内容!
  2. 需要对字符串进行排序或判断大小顺序?

    • 区分大小写:使用 str1.compareTo(str2)
    • 不区分大小写:使用 str1.compareToIgnoreCase(str2)
  3. 什么时候用 比较字符串?

    • 几乎没有业务场景需要用到。
    • 一个典型的场景是性能优化:当你确定两个字符串变量必须指向同一个对象时(从一个缓存中获取),可以用 来快速判断,因为它比 equals() 更快(直接比较地址,不用逐个字符比较),但这属于高级优化技巧,初学者应避免。

记住黄金法则:

比较字符串内容,用 equals();比较字符串顺序,用 compareTo();比较对象引用,用 。

分享:
扫描分享到社交APP
上一篇
下一篇