如何比较Java中的字符串?

如何比较Java中的字符串?,java,string,equality,Java,String,Equality,到目前为止,我一直在程序中使用==运算符来比较所有字符串。 然而,我遇到了一个bug,将其中一个改为.equals,它修复了这个bug 坏吗?什么时候应该使用,什么时候不应该使用?有什么区别吗?==测试它们是否是同一对象的引用相等性 .equals测试值是否相等,逻辑上是否相等 在调用.equals之前检查null,这样您就不必从JDK7开始就可用,也可以在中使用 因此,如果要测试两个字符串是否具有相同的值,可能需要使用Objects.equals 您几乎总是希望使用Objects.equals

到目前为止,我一直在程序中使用==运算符来比较所有字符串。 然而,我遇到了一个bug,将其中一个改为.equals,它修复了这个bug

坏吗?什么时候应该使用,什么时候不应该使用?有什么区别吗?

==测试它们是否是同一对象的引用相等性

.equals测试值是否相等,逻辑上是否相等

在调用.equals之前检查null,这样您就不必从JDK7开始就可用,也可以在中使用

因此,如果要测试两个字符串是否具有相同的值,可能需要使用Objects.equals

您几乎总是希望使用Objects.equals。在处理字符串的罕见情况下,可以使用==

发件人:

此外,字符串文字总是引用类字符串的同一实例。这是因为使用string.intern方法对字符串文本(或者更一般地说,是常量表达式的值的字符串)进行了插入,以便共享唯一的实例

类似的例子也可以在中找到

其他考虑方法 忽略大小写的值相等。但是,请注意,在各种与区域设置相关的情况下,此方法可能会产生意外的结果,请参阅

将字符串的内容与自Java 1.5以来可用的任何CharSequence的内容进行比较。不必在进行相等比较之前将StringBuffer等转换为字符串,但将空检查留给您。

是的,==不适合比较字符串和任何对象,除非您知道它们是规范的。==只是比较对象引用。相等检验相等。对于字符串,它们通常是相同的,但正如您所发现的,这并不总是保证的。

==比较Java中的对象引用,对于字符串对象也不例外

为了比较包括字符串在内的对象的实际内容,必须使用equals方法

如果使用==对两个字符串对象进行比较的结果为真,那是因为字符串对象已被插入,并且Java虚拟机有多个引用指向同一个字符串实例。我们不应该期望使用==将一个包含相同内容的字符串对象与另一个字符串对象进行比较,从而计算为true。

是的,这是不好的

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

Equals为您进行真正的比较

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

==如果两个不谈论基本体的对象指向同一个对象实例,则返回true。 .equals如果两个对象包含相同的数据,则返回true

这可能会对您有所帮助。

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

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

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方法对内容进行逐个字符的比较

当为a和b调用new时,每一个都会得到一个指向字符串表中foo的新引用。引用不同,但内容相同。

==测试对象引用,.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";
但是要当心空值

==可以处理空字符串,但从空字符串调用.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:

System.out.print("bar".equals(fooString1));  // "bar" is never null
System.out.print(Objects.equals(fooString1, "bar"));  // Java 7 required

我同意zacherates的回答

但你能做的是在你的非文字字符串上调用intern

来自zacherates的例子:

// ... but they are not the same object
new String("test") == "test" ==> false 
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.")
}
如果实习,则非文字字符串相等为真:


Java中的字符串是不可变的。这意味着无论何时尝试更改/修改字符串,都会得到一个新实例。不能更改原始字符串。这样做是为了缓存这些字符串实例。一个典型的程序包含很多字符串引用,缓存这些实例可以减少内存占用并提高程序的性能

当使用==运算符进行字符串比较时,您不是在比较字符串的内容,而是在比较内存地址。如果他们两个相等,它将是r 否则,请返回true和false。而字符串中的equals比较字符串内容

所以问题是,如果所有字符串都缓存在系统中,那么为什么==返回false而equals返回true?嗯,这是可能的。如果创建一个新字符串,如string str=new StringTesting,那么即使缓存中已经包含具有相同内容的字符串,也会在缓存中创建一个新字符串。简而言之,MyString==newstringmystring将始终返回false

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


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

==比较对象的参考值,而java.lang.String类中的equals方法将字符串对象的内容与另一个对象进行比较。

所有对象都保证有.equals方法,因为对象包含返回布尔值的.equals方法。如果需要进一步的定义,子类的任务是重写此方法。没有它,即使用==仅检查两个对象之间的内存地址是否相等。String重写此.equals方法,它不使用内存地址,而是在字符级别返回字符串的比较以实现相等

值得注意的是,字符串存储在一个一次性池中,因此一旦创建了字符串,它将永远存储在同一地址的程序中。字符串不会更改,它们是不可变的。这就是为什么如果您有大量的字符串处理要做,那么使用常规字符串连接是个坏主意。相反,您将使用提供的StringBuilder类。请记住,指向该字符串的指针可能会发生变化,如果您有兴趣查看两个指针是否相同,那么==将是一个不错的选择。字符串本身不是。比较对象引用

.equals比较字符串值

有时==会产生比较字符串值的错觉,如以下情况:

String a="Test";
String b="Test";
if(a==b) ===> true
这是因为,当您创建任何字符串文字时,JVM首先在字符串池中搜索该文字,如果找到匹配项,则会向新字符串提供相同的引用。因此,我们得到:

a==b==>true

在本例中,对于new Stringtest,语句new String将在堆上创建,并且该引用将被赋予b,因此b将被赋予堆上的引用,而不是字符串池中的引用

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

ifa==b===>false


因此,使用.equals总是更好。

我认为定义字符串时,就是定义对象。所以你需要使用。等于。使用基本数据类型时,使用==但必须使用字符串和任何对象。等于。

函数:

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()));
}
==执行引用相等检查,在这种情况下,两个对象字符串是否引用内存中的同一对象

equals方法将检查两个对象的内容或状态是否相同

显然==更快,但如果您只想知道两个字符串是否包含相同的文本,则在许多情况下可能会给出错误的结果

当然,建议使用equals方法

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

String.equals的实现首先使用==检查引用相等性,如果两个字符串通过引用相同,则不执行进一步的计算! 如果两个字符串引用不相同,string.equals将接下来检查字符串的长度。这也是一个快速的操作,因为String类存储字符串的长度,不需要计算字符或代码点。如果长度不同,则不进行进一步检查,我们知道它们不能相等。 只有到了这一步,才会对两个字符串的内容进行实际比较,这将是一个简单的比较:不会对所有字符进行比较,如果我们在两个字符串的同一位置发现不匹配的字符,则不会再检查其他字符。
说到底,即使我们保证字符串是实习生,使用equals方法仍然不会像人们认为的那样带来开销,这绝对是推荐的方法。如果您想要有效的引用检查,那么在语言规范和实现保证相同的枚举值通过引用将是相同的对象的地方使用枚举。

Java有一个字符串池,Java在其中管理字符串对象的内存分配。看

当您使用==运算符选中“比较两个对象”时,它会将地址相等性比较到字符串池中。如果两个字符串对象具有相同的地址引用 然后返回true,否则返回false。但如果要比较两个字符串对象的内容,则必须重写equals方法

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

Example:
    stringObjectOne.equals(stringObjectTwo);
但请注意,它尊重字符串的情况。如果希望进行不区分大小写的比较,则必须使用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
运算符==始终用于对象引用比较,而字符串类.equals方法则用于内容比较:

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


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

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

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

选项1:使用equals方法比较Java字符串 大多数情况下,我可能有95%的时间将字符串与Java String类的equals方法进行比较,如下所示:

if (string1.equals(string2))
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.")
 }
此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,如本例所示:

// ... but they are not the same object
new String("test") == "test" ==> false 
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方法,如下所示:

if (string1.equals(string2))
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对象类中包含一个equals方法。每当您创建自己的对象并且希望提供一种方法来查看对象的两个实例是否相等时,您应该在类中重写并实现此equals方法,就像Java语言在String equals方法中提供此相等/比较行为一样

您可能想看看这个==操作符,检查两个引用是否指向同一个对象。等于检查实际字符串内容值

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

案例1

原因:创建的不带null的字符串文本存储在堆的permgen区域的字符串池中。所以s1和s2都指向池中的同一个对象

案例2

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

如果equals方法存在于java.lang.Object类中,那么它应该检查对象状态的等价性!也就是说,对象的内容。而==运算符则需要检查实际对象实例是否相同

范例

考虑两个不同的参考变量,str1和str2:

如果你用等号

如果使用==,则输出为TRUE

现在您将得到FALSE作为输出,因为str1和str2都指向两个不同的对象,即使它们共享相同的字符串内容。这是因为新字符串每次都会创建一个新对象。

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

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

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

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

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


有时看起来好像==比较值,-==总是比较值!只是某些值是引用!遗憾的是,isNullOrEmpty没有静态方法,也没有自定义的操作符重载,这使得Java的这一部分比C或Python更笨重。由于Java没有扩展方法,所以您不能编写自己的实用程序来扩展Java.lang.String。正当关于对字符串进行子类化,添加静态实用程序方法,然后总是使用MyString,有什么想法吗?在该子类中也可以使用一个带有两个参数的静态方法来进行空安全比较?。。这将转换为nullString1?.equalNullString2;变成一个完全空的语句。但是,如果您有validString?.equalsnullString;-这仍然引发了一个异常。比较java中可空字符串的短方法:@JonCoombs java支持子类化和创建自己的方法。然而,由于某些原因,很少有类被标记为final,String就是其中之一,所以我们无法扩展。我们可以创建另一个类,并在那个里创建实用程序类,它以两个字符串作为参数,并在那个里实现我们的逻辑。另外,对于null检查,一些其他库,如spring和apache,可以使用这些方法。不要吹毛求疵,但是String的方法实际上在String类中,而不是在Object中。对象中的默认值不会比较内容是否相同,事实上,当引用相同时,只返回true。@JacobSchoen:由于GrepCode关闭,上述链接不再起作用。以下是equals实现的备选方案:[内联链接]我发现这是一个大问题的迟来答案。我可以问一下,它提供了哪些在现有答案中没有提到的内容吗?@Mysticial他添加了equalsIgnoreCase,这可能会为新手提供信息;字符串string2=foo-bar;您可以直接使用==运算符在google apps脚本中测试内容相等性,但不可能进行比较。我尝试了instaed equals,这是唯一有效的解决方案……而且很高兴知道,如果您正在重写.equals方法,请确保您正在重写.hashcode方法,否则您将最终违反等效关系b/w equals和hashcode。有关更多信息,请参阅java文档。留下一个链接,指向我的解释,解释为什么==在对象上的工作方式:==有时会工作,因为java有一个字符串池,它尝试重用常用字符串的内存引用。但是==比较对象是否相等,而不是值是否相等。。。因此.equals是您想要使用的正确用法。永远不要使用==来测试字符串是否相同,除非您喜欢跟踪细微错误并研究Java字符串内部过程的复杂性。12==1+2为假,可能一旦创建了字符串,它就永远存储在同一地址的程序中——这完全是错误的。只有编译时常量字符串表达式(可能涉及最终字符串变量)和程序显式插入的字符串存储在您称之为一次性池中。与任何其他类型的对象一样,一旦不再有对其他字符串对象的活动引用,所有其他字符串对象都将接受垃圾收集。此外,虽然整个interning机制需要不变性才能工作,但这与此无关。字符串比较可以通过equals或equalsIgnoreCase方法完成,该方法实际比较字符串的内容。但是==符号只需检查参考值。对于这种情况,字符串池中的字符串文本可以正常工作。字符串s1=新字符串A;字符串s2=新的字符串A;在本例中,s1==s2为false,但s1.equals2为true。除非其中一个为null,否则s.equals2将在s为null时崩溃,导致比较失败。当然,这与答案并不矛盾;这只是一个警告。不,它不会崩溃,它会抛出NullPointerException,导致比较无法进行。通常我强烈建议apache commons库:,java.lang.Stringchar[]不是原始数据类型!这是一个字符数组。数组本身不是原始数据类型。这与其他答案有什么不同?你为什么要这样做suggest@Mark关于==和equals之间的差异的问题已经由其他解决方案回答了
,我只是提供了一种不同的方法来比较字符串,这通常不是一个好主意。实习成本相对较高,而且可能会矛盾地增加>>equals会比较这两个实例,但是会实现equals来比较它们。这可能是也可能不是比较toString的输出。@Jacob Object class.equals方法将InstanceReferences/Address作为String类进行比较。equals方法被重写以比较contentcharsGood指出字符串池与Java堆的差异,因为它们肯定不相同。在字符串池中,Java试图缓存字符串对象以节省内存占用,因为字符串是不可变的,我希望,我在这里说得对。同时检查这是我一直在寻找的答案。多好的答案啊!显然==更快-实际上.equalString的实现首先检查==然后再做其他任何事情,所以我想说速度大约相同.public boolean equalobject anObject{if this==anObject{return true;}…如果==检查引用相等,为什么n==5有意义?5不是variable@HritRoy因为==检查变量的值。当您有一个对象时,引用该对象的变量将对象的引用作为值。因此,当您使用==比较两个变量时,会比较引用。当比较基本数据类型时作为int,情况仍然是一样的。int类型的变量的值是整数。因此,您可以使用==来比较两个int的值。如果int是变量的值或幻数,则无所谓。此外:引用只不过是引用内存的数字。我想补充一点,即使您知道字符串被插入,yo你应该使用equals,因为它更明显是正确的。或者,你应该使用枚举而不是字符串。
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.")
}
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.")
 }
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.")
}
String s1 = "Stack Overflow";
String s2 = "Stack Overflow";
s1 == s2;      //true
s1.equals(s2); //true
String s1 = new String("Stack Overflow");
String s2 = new String("Stack Overflow");
s1 == s2;      //false
s1.equals(s2); //true
str1 = new String("abc");
str2 = new String("abc");
System.out.println((str1.equals(str2))?"TRUE":"FALSE");
System.out.println((str1==str2) ? "TRUE" : "FALSE");