如何在Java中比较字符串?

723

目前我在程序中一直使用==运算符来比较所有的字符串。然而,我遇到了一个错误,将其中一个用.equals()替换后,问题被解决了。

==是否不好?应该何时使用或不使用?有什么区别?


12
同时需要注意的是,如果你要重写 .equals() 方法,确保你也要重写 .hashcode() 方法,否则你将违反 equals 和 hashcode 之间的等价关系。如需更多信息,请参考Java文档。 - Nageswaran
这里是我对于 == 在对象上运作方式的解释链接:http://stackoverflow.com/a/19966154/2284641 - Johannes H.
"==" 有时会起作用,因为 Java 有一个字符串池,它试图重用常用字符串的内存引用。但是 "==" 比较的是对象是否相等,而不是值... 所以你应该使用 ".equals()" 来比较值。 - James Oravec
除非你喜欢追踪微妙的错误并研究Java字符串内部化过程的复杂性,否则不要使用“==”来测试字符串是否相同。 "12" == "1" + 2 是错误的(可能)。 - Flight Odyssey
23个回答

105

==在Java中比较对象引用,对于String对象也不例外。

如果要比较对象的实际内容(包括String),必须使用equals方法。

如果使用==比较两个String对象,结果为true,那是因为这些String对象被interned了,Java虚拟机有多个引用指向同一个String实例。不能期望将包含与另一个String对象相同内容的一个String对象与另一个String对象使用==进行比较,其结果为true


102

.equals()方法比较类中的数据(假设函数已实现)。 ==比较指针位置(对象在内存中的位置)。

==仅当两个对象(非基本类型)指向同一对象实例时返回true。 .equals()仅当两个对象包含相同的数据时返回true。equals()==在Java中的区别

这可能会对您有所帮助。


101

==执行引用(reference)的相等性检查,即检查这两个对象(在本例中为字符串)是否指向内存中的同一对象。

equals()方法将检查2个对象的内容状态是否相同。

显然,==更快,但如果您只想判断2个String是否具有相同的文本,则可能会产生错误结果。

绝对建议使用equals()方法。

不必担心性能。以下是一些鼓励使用String.equals()的原因:

  1. String.equals()的实现首先检查引用相等性(使用==),如果2个字符串引用相同,则不执行进一步计算!
  2. 如果2个字符串引用不同,则String.equals()将接下来检查字符串的长度。这也是一个快速操作,因为String类存储了字符串的长度,不需要计算字符或代码点。如果长度不同,则不执行进一步检查,我们知道它们不能相等。
  3. 仅当我们到达这一步时,才会实际比较2个字符串的内容,并且这将是一种简写比较:不会比较所有字符,如果我们发现不匹配的字符(在2个字符串的相同位置),则不会再检查其他字符。

说到底,即使我们保证字符串是内部化的,使用equals()方法仍然不会产生太多负担,绝对是推荐的方式。如果您想要高效的引用检查,则可以使用枚举,因为语言规范和实现保证相同的枚举值将是同一对象(通过引用)。


2
显然,使用“==”更快--实际上,“.equals(String)”函数的实现在执行任何其他操作之前都会先进行“==”比较,因此我认为速度几乎相同。 - Razzle Shazl
2
public boolean equals(Object anObject) { if (this == anObject) { return true; } ... - Razzle Shazl

84

如果你和我一样,当我第一次开始使用Java时,想要使用"=="运算符来测试两个String实例是否相等,但无论好坏,这在Java中都不是正确的方法。

在本教程中,我将展示几种不同的正确比较Java字符串的方法,从我大多数情况下使用的方法开始。在这个Java String比较教程的结尾处,我也会讨论为什么"=="运算符在比较Java字符串时不起作用。

选项1:使用equals方法进行Java字符串比较 大多数时间(也许95%的时间),我使用Java String类的equals方法来比较字符串,像这样:

if (string1.equals(string2))

这个字符串相等的方法检查两个Java字符串,如果它们包含完全相同的一组字符,则认为它们是相等的。

通过使用equals方法来进行快速字符串比较的例子,如果运行以下测试,则这两个字符串不会被认为是相等的,因为字符并不完全相同(字符的大小写不同):

String string1 = "foo";
String string2 = "FOO";

if (string1.equals(string2))
{
    // this line will not print because the
    // java string equals method returns false:
    System.out.println("The two strings are the same.")
}

但是,当两个字符串包含完全相同的字符时,equals方法将返回true,就像这个例子:

String string1 = "foo";
String string2 = "foo";

// test for equality with the java string equals method
if (string1.equals(string2))
{
    // this line WILL print
    System.out.println("The two strings are the same.")
}

选项2:使用equalsIgnoreCase方法进行字符串比较

在某些字符串比较测试中,你可能希望忽略字符串是大写还是小写。当你想以这种不区分大小写的方式测试字符串相等性时,可以使用String类的equalsIgnoreCase方法,像这样:

String string1 = "foo";
String string2 = "FOO";

 // java string compare while ignoring case
 if (string1.equalsIgnoreCase(string2))
 {
     // this line WILL print
     System.out.println("Ignoring case, the two strings are the same.")
 }

选项3:使用compareTo方法进行Java字符串比较

还有第三种不常见的方法来比较Java字符串,就是使用String类的compareTo方法。如果两个字符串完全相同,compareTo方法将返回值0(零)。以下是演示这种字符串比较方法的快速示例:

String string1 = "foo bar";
String string2 = "foo bar";

// java string compare example
if (string1.compareTo(string2) == 0)
{
    // this line WILL print
    System.out.println("The two strings are the same.")
}

在我写Java平等概念时,需要注意Java语言的基础类Java Object中包含一个equals方法。如果您正在创建自己的对象并想提供一种方法来判断两个实例是否“相等”,则应该在您的类中覆盖(并实现)此equals方法 (与Java语言在String equals方法中提供相同的平等/比较行为的方式相同)。

您可能需要查看这个==、.equals()、compareTo()和compare()


5
对于字符串字面值,比如 String string1 = "foo bar"; String string2 = "foo bar"; ,你可以直接使用 == 运算符来测试内容是否相等。 - JAVA
1
在Google Apps Script中,“compareTo”不可用。我尝试使用“equals”代替。这是唯一可行的解决方案... - Rob
最后分享的链接已经无法使用,您可能需要更改它。 - spats

80
==运算符检查两个引用是否指向同一个对象。.equals()方法检查实际字符串内容(值)。

请注意,.equals()方法属于Object类(所有类的超类)。您需要根据您的类要求重写它,但对于String类型,已经实现了它,并且它检查两个字符串是否具有相同的值。

  • 情况1

    String s1 = "Stack Overflow";
    String s2 = "Stack Overflow";
    s1 == s2;      //true
    s1.equals(s2); //true
    

    原因:没有带有null的字符串文字存储在堆的permgen区域中的字符串池中。因此,s1和s2都指向池中的同一对象。

  • 情况2

    String s1 = new String("Stack Overflow");
    String s2 = new String("Stack Overflow");
    s1 == s2;      //false
    s1.equals(s2); //true
    

    原因:如果您使用new关键字创建一个字符串对象,则会在堆上分配一个单独的空间。


80

功能:

public float simpleSimilarity(String u, String v) {
    String[] a = u.split(" ");
    String[] b = v.split(" ");

    long correct = 0;
    int minLen = Math.min(a.length, b.length);

    for (int i = 0; i < minLen; i++) {
        String aa = a[i];
        String bb = b[i];
        int minWordLength = Math.min(aa.length(), bb.length());

        for (int j = 0; j < minWordLength; j++) {
            if (aa.charAt(j) == bb.charAt(j)) {
                correct++;
            }
        }
    }

    return (float) (((double) correct) / Math.max(u.length(), v.length()));
}

测试:

String a = "This is the first string.";

String b = "this is not 1st string!";

// for exact string comparison, use .equals

boolean exact = a.equals(b);

// For similarity check, there are libraries for this
// Here I'll try a simple example I wrote

float similarity = simple_similarity(a,b);

6
这与其他答案有何不同?为什么要按照您建议的方式进行呢? - mmmmmm
2
@Mark 其他解决方案已经回答了“==”和“equals”的区别问题,我只是提供了一种宽松比较字符串的不同方式。 - Khaled.K

55

== 比较对象的引用值,而 java.lang.String 类中的 equals() 方法则比较 String 对象的内容(与另一个对象比较)。


15
equals() 方法用于比较两个对象是否相等,针对 String 类而言,其实际上是定义在 String 类中,而非 Object 类中。默认的 equals() 方法实现只会比较对象的引用,而不会判断对象内容是否相等。因此,在比较 String 对象时需要使用 String 类的 equals() 方法来确保比较的是对象内容是否相等。 - Jacob Schoen
1
@JacobSchoen:上面的链接已经失效了,因为GrepCode已经关闭。这里提供一个equals实现的替代方案:[内联链接](https://zgrepcode.com/java/openjdk/10.0.2/java.base/java/lang/string.java#L-1000) - Amandeep Singh

52

我认为当你定义一个 String 时,你定义了一个对象。所以你需要使用 .equals()。当你使用原始数据类型时,你使用 ==,但是对于 String(和任何对象),你必须使用 .equals()


7
"char[]"不是基本数据类型!它是一个"char"数组。而数组本身不是基本数据类型。" - Christian

50
如果在java.lang.Object类中存在equals()方法,并且期望检查对象状态的等价性!这意味着对象的内容。而==运算符则用于检查实际对象实例是否相同。

示例

考虑两个不同的引用变量str1str2

str1 = new String("abc");
str2 = new String("abc");

如果您使用 equals()

System.out.println((str1.equals(str2))?"TRUE":"FALSE");

如果你使用==,你将得到TRUE作为输出结果。

System.out.println((str1==str2) ? "TRUE" : "FALSE");

现在你会得到FALSE作为输出,因为尽管它们都共享相同的字符串内容,但str1str2指向两个不同的对象。这是因为每次使用new String()创建一个新对象。


46

运算符==始终用于对象引用比较,而String类的.equals()方法被覆盖以进行内容比较

String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1 == s2); // It prints false (reference comparison)
System.out.println(s1.equals(s2)); // It prints true (content comparison)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接