如何比较Java中的字符串?

时间:2009-02-04 23:17:08

标签: java string equality

到目前为止,我一直在我的程序中使用==运算符来比较我的所有字符串。 但是,我遇到了一个错误,将其中一个更改为.equals(),然后修复了错误。

==不好吗?什么时候应该不应该使用它?有什么区别?

23 个答案:

答案 0 :(得分:5329)

==测试引用相等性(它们是否是同一个对象)。

.equals()测试值相等(它们在逻辑上是否“相等”)。

在调用null之前,

Objects.equals()会检查.equals(),因此您不必(从JDK7开始,Guava中也可用)。

String.contentEquals()String的内容与任何CharSequence的内容进行比较(自Java 1.5起可用)。

因此,如果您想测试两个字符串是否具有相同的值,您可能希望使用Objects.equals()

// These two have the same value
new String("test").equals("test") // --> true 

// ... but they are not the same object
new String("test") == "test" // --> false 

// ... neither are these
new String("test") == new String("test") // --> false 

// ... but these are because literals are interned by 
// the compiler and thus refer to the same object
"test" == "test" // --> true 

// ... string literals are concatenated by the compiler
// and the results are interned.
"test" == "te" + "st" // --> true

// ... but you should really just call Objects.equals()
Objects.equals("test", new String("test")) // --> true
Objects.equals(null, "test") // --> false
Objects.equals(null, null) // --> true

您几乎始终想要使用Objects.equals()。在罕见的情况下,知道您正在处理interned字符串,可以使用==。< / p>

来自JLS 3.10.5. String Literals

  

此外,字符串文字始终引用类String相同实例。这是因为字符串文字 - 或者更常见的是作为常量表达式(§15.28)的值的字符串 - 被“实现”以便使用方法String.intern共享唯一实例。

类似的例子也可以在JLS 3.10.5-1中找到。

答案 1 :(得分:688)

==测试对象引用,.equals()测试字符串值。

有时它看起来好像==比较值,因为Java会做一些幕后的事情来确保相同的内联字符串实际上是同一个对象。

例如:

String fooString1 = new String("foo");
String fooString2 = new String("foo");

// Evaluates to false
fooString1 == fooString2;

// Evaluates to true
fooString1.equals(fooString2);

// Evaluates to true, because Java uses the same object
"bar" == "bar";

但要注意空值!

==处理null个字符串很好,但是从空字符串调用.equals()会导致异常:

String nullString1 = null;
String nullString2 = null;

// Evaluates to true
System.out.print(nullString1 == nullString2);

// Throws a NullPointerException
System.out.print(nullString1.equals(nullString2));

因此,如果您知道fooString1可能为null,请通过编写

告诉读者
System.out.print(fooString1 != null && fooString1.equals("bar"));

以下内容较短,但检查null(来自Java 7)不太明显:

System.out.print(Objects.equals(fooString1, "bar"));

答案 2 :(得分:424)

==比较对象引用。

.equals()比较字符串值。

有时==会出现比较字符串值的错觉,如下列情况:

String a="Test";
String b="Test";
if(a==b) ===> true

这是因为当您创建任何字符串文字时,JVM首先在字符串池中搜索该字面值,如果找到匹配项,则将为新字符串指定相同的引用。因此,我们得到:

(a == b)===&gt;真

                       String Pool
     b -----------------> "test" <-----------------a

但是,==在以下情况下失败:

String a="test";
String b=new String("test");
if (a==b) ===> false

在这种情况下,new String("test")语句将在堆上创建新的String,并且该引用将被赋予b,因此b将在堆上被赋予引用,而不是在字符串池中。

现在a指向String池中的String,而b指向堆上的String。因此我们得到:

if(a == b)===&gt;假

                String Pool
     "test" <-------------------- a

                   Heap
     "test" <-------------------- b

虽然.equals()总是比较String的值,所以在两种情况下它都给出:

String a="Test";
String b="Test";
if(a.equals(b)) ===> true

String a="test";
String b=new String("test");
if(a.equals(b)) ===> true

所以使用.equals()总是更好。

答案 3 :(得分:217)

==运算符检查两个字符串是否完全相同。

.equals()方法将检查两个字符串是否具有相同的值。

答案 4 :(得分:172)

Java中的字符串是不可变的。这意味着每当您尝试更改/修改字符串时,您将获得一个新实例。您无法更改原始字符串。这样做是为了可以缓存这些字符串实例。典型的程序包含大量的字符串引用和缓存这些实例可以减少内存占用并提高程序的性能。

使用==运算符进行字符串比较时,您不是要比较字符串的内容,而是实际比较内存地址。如果它们都相等,则返回true和false。而字符串中的equals则比较字符串内容。

所以问题是如果所有字符串都缓存在系统中,那么==如何返回false而equals返回true?嗯,这是可能的。如果你创建一个像String str = new String("Testing")这样的新字符串,你最终会在缓存中创建一个新字符串,即使缓存已经包含一个具有相同内容的字符串。简而言之,"MyString" == new String("MyString")将始终返回false。

Java还讨论了函数intern(),它可以在字符串上使用,使其成为缓存的一部分,因此"MyString" == new String("MyString").intern()将返回true。

注意:==运算符比equals快得多,因为您要比较两个内存地址,但是您需要确保代码没有在代码中创建新的String实例。否则你会遇到错误。

答案 5 :(得分:142)

String a = new String("foo");
String b = new String("foo");
System.out.println(a == b); // prints false
System.out.println(a.equals(b)); // prints true

确保您了解原因。这是因为==比较仅比较参考; equals()方法对内容进行逐字符比较。

当您为ab调用new时,每个人都会获得一个新的引用,该引用指向字符串表中的"foo"。引用不同,但内容相同。

答案 6 :(得分:125)

是的,这很糟糕......

==表示您的两个字符串引用完全相同。您可能听说过这种情况,因为Java保留了一个文字表(它确实如此),但情况并非总是如此。有些字符串以不同的方式加载,由其他字符串等构成,因此您绝不能假设两个相同的字符串存储在同一位置。

等于你真正的比较。

答案 7 :(得分:121)

是的,==不适合比较字符串(任何对象,除非你知道它们是规范的)。 ==只是比较对象引用。 .equals()测试平等。对于Strings来说,它们通常都是相同的,但正如你所发现的那样,总是不能保证。

答案 8 :(得分:112)

Java有一个String池,Java管理String对象的内存分配。见String Pools in Java

使用==运算符检查(比较)两个对象时,它会将地址相等性与字符串池进行比较。如果两个String对象具有相同的地址引用,则返回true,否则返回false。但是,如果要比较两个String对象的内容,则必须覆盖equals方法。

equals实际上是Object类的方法,但它被重写到String类中,并给出了一个比较对象内容的新定义。

Example:
    stringObjectOne.equals(stringObjectTwo);

但是请注意它尊重String的情况。如果你想要不区分大小写,那么你必须使用String类的equalsIgnoreCase方法。

让我们看看:

String one   = "HELLO"; 
String two   = "HELLO"; 
String three = new String("HELLO"); 
String four  = "hello"; 

one == two;   // TRUE
one == three; // FALSE
one == four;  // FALSE

one.equals(two);            // TRUE
one.equals(three);          // TRUE
one.equals(four);           // FALSE
one.equalsIgnoreCase(four); // TRUE

答案 9 :(得分:99)

==比较Java中的对象引用String个对象也不例外。

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

如果使用String对两个==对象的比较结果为true,那是因为String对象被实习,而Java虚拟机正在使用多个引用指向String的同一个实例。我们不应期望使用String将包含相同内容的一个String对象与另一个==对象进行比较,以评估为true

答案 10 :(得分:98)

我同意zacherates的答案。

但你可以做的就是在你的非文字字符串上调用intern()

来自zacherates示例:

// ... but they are not the same object
new String("test") == "test" ==> false 

如果您实习非文字字符串相等为true

new String("test").intern() == "test" ==> true 

答案 11 :(得分:97)

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

如果两个对象(不是关于PRIMITIVES的对话)指向SAME对象实例,则

==返回true。 如果两个对象包含相同的数据equals() Versus == in Java

,则.equals()返回true

这可能对你有所帮助。

答案 12 :(得分:93)

==执行引用等式检查,无论2个对象(本例中为字符串)是否引用内存中的同一对象。

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

显然==更快,但如果您只是想知道2 String是否持有相同的文字,那么在许多情况下会(可能)会给出错误的结果。

建议使用equals()方法。

不要担心性能。鼓励使用String.equals()的一些事情:

  1. String.equals()的实现首先检查引用相等性(使用==),如果2个字符串通过引用相同,则不再执行计算!
  2. 如果2个字符串引用不相同,String.equals()将接下来检查字符串的长度。这也是一个快速操作,因为String类存储字符串的长度,不需要计算字符或代码点。如果长度不同,不再进行进一步检查,我们知道它们不相等。
  3. 只有当我们到达这一点时才会真正比较2个字符串的内容,这将是一个简短的比较:如果我们找到一个不匹配的字符(在同一位置,则不会比较所有字符) 2个字符串),不会检查其他字符。
  4. 当完成所有操作后,即使我们保证字符串是实习生,使用equals()方法仍然不是人们可能认为的开销,绝对是推荐的方法。如果你想要有效的参考检查,那么使用枚举,语言规范和实现保证相同的枚举值将是同一个对象(通过引用)。

答案 13 :(得分:81)

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

在本教程中,我将演示几种不同的方法来正确比较Java字符串,从我大多数时候使用的方法开始。在Java String比较教程的最后,我还将讨论为什么“==”运算符在比较Java字符串时不起作用。

选项1:使用equals方法进行Java字符串比较 大部分时间(可能是95%的时间)我将字符串与Java String类的equals方法进行比较,如下所示:

if (string1.equals(string2))

此String equals方法查看两个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比较方法的简单示例:

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(), and compare()

答案 14 :(得分:76)

功能:

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);

答案 15 :(得分:73)

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

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

  • 案例1

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

    原因:在没有null的情况下创建的字符串文字存储在堆的permgen区域的String池中。所以s1和s2都指向池中的同一个对象。

  • 案例2

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

    原因:如果使用new关键字创建String对象,则会在堆上为其分配单独的空间。

答案 16 :(得分:52)

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

答案 17 :(得分:49)

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

答案 18 :(得分:46)

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

实施例

考虑两个不同的参考变量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()每次都会创建一个新对象。

答案 19 :(得分:42)

运算符 == 始终用于对象引用比较,而 .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)

答案 20 :(得分:38)

所有对象都保证具有.equals()方法,因为Object包含一个返回布尔值的方法.equals()。如果需要进一步的定义定义,则覆盖此方法是子类的工作。没有它(即使用==),仅在两个对象之间检查存储器地址是否相等。字符串覆盖此.equals()方法,而不是使用内存地址,它返回字符级别的字符串比较以获得相等性。

一个关键的注意事项是字符串存储在一个块池中,因此一旦创建了一个字符串,它就永远存储在同一地址的程序中。字符串不会改变,它们是不可变的。这就是为什么如果你要进行大量的字符串处理,使用常规字符串连接是一个坏主意。相反,您将使用提供的StringBuilder类。请记住,指向此字符串的指针可以更改,如果您有兴趣查看两个指针是否相同==将是一个很好的方法。字符串本身没有。

答案 21 :(得分:38)

您还可以使用compareTo()方法比较两个字符串。如果compareTo结果为0,则两个字符串相等,否则被比较的字符串不相等。

==比较引用并且不比较实际的字符串。如果您确实使用new String(somestring).intern()创建了每个字符串,那么您可以使用==运算符来比较两个字符串,否则只能使用equals()或compareTo方法。

答案 22 :(得分:34)

在Java中,当“==”运算符用于比较2个对象时,它会检查对象是否引用内存中的相同位置。换句话说,它检查2个对象名称是否基本上是对同一内存位置的引用。

Java String类实际上覆盖了Object类中的默认equals()实现 - 它覆盖了该方法,因此它只检查字符串的值,而不是它们在内存中的位置。  这意味着如果调用equals()方法来比较2个String对象,那么只要实际的字符序列相等,两个对象就被认为是相等的。

  

==运算符检查两个字符串是否完全相同。

     

.equals()方法检查两个字符串是否具有相同的值。