如何比较Java中的字符串?

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

==不好吗?什么时候该用,什么时候不该用?有什么区别?

4439171 次浏览

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

.equals()测试值相等性(它们是否包含相同的数据)。

Objects.equals()在调用.equals()之前检查null,因此您不必这样做(从JDK7开始可用,在番石榴中也可用)。

因此,如果您想测试两个字符串是否具有相同的值,您可能希望使用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()。在罕见的情况下,你知道处理被拘留字符串,你可以使用==

来自JLS 3.10.5。字符串文字

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

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

其他方法考虑

String.equalsIgnoreCase()值相等,忽略大小写。但是,请注意,此方法可能在各种与语言环境相关的情况下产生意外结果,请参阅这个问题

String.content等于()String的内容与任何CharSequence的内容(自Java1.5起可用)进行比较。使您不必在进行相等比较之前将StringBuffer等转换为String,但将空值检查留给您。

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

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

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

如果使用==比较两个String对象结果是true,那是因为String对象被扣留,并且Java虚拟机有多个引用指向String的同一个实例。不应期望使用==比较一个String对象与另一个String对象包含相同内容以评估为true

是啊很糟糕…

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

平等为你做真正的比较。

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

==如果两个对象(不是谈论PRIMITIVES)都指向同一个对象实例,则返回true。 .equals()如果两个对象包含相同的数据,则返回true#EYZ1与==在Java

这可能对你有帮助。

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

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

当您为ab调用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";

但要小心空值!

==可以很好地处理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可能为空,请通过编写来告诉读者

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

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

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

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

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

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

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

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

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

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

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

==比较对象引用。

.equals()比较字符串值。

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

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

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

(a==b) ===> true

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

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

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

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

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

如果(a==b) ===> false。

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


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

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

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()总是更好。

我认为当您定义String时,您定义了一个对象。所以您需要使用.equals()。当您使用原始数据类型时,您使用==,但对于String(和任何对象),您必须使用.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()));
}

测试:

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

==执行参考相等性检查,检查2个对象(在本例中为字符串)是否引用内存中的同一个对象。

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

显然,==更快,但如果您只想判断2String是否包含相同的文本,则在许多情况下会(可能)给出错误的结果。

绝对推荐使用equals()方法。

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

  1. String.equals()的实现首先检查引用是否相等(使用==),如果两个字符串的引用相同,则不执行进一步的计算!
  2. 如果2个字符串引用不相同,String.equals()接下来将检查字符串的长度。这也是一个快速操作,因为String类存储字符串的长度,不需要计算字符或代码点。如果长度不同,不执行进一步的检查,我们知道它们不可能相等。
  3. 只有当我们得到这一点时,才会实际比较2个字符串的内容,这将是一个简短的比较:不是所有的字符都会被比较,如果我们发现一个不匹配的字符(在2个字符串中的相同位置),就不会检查更多的字符。

说到底,即使我们保证字符串是实习生,使用equals()方法仍然没有人们可能认为的开销,绝对是推荐的方式。如果你想进行有效的引用检查,那么在语言规范和实现保证相同枚举值将是相同对象(通过引用)的地方使用枚举。

Java有一个String池,Java在其中管理String对象的内存分配。

当您使用==运算符检查(比较)两个对象时,它会将地址相等性与字符串池进行比较。如果两个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

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

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

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

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

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

选项1:JavaString与equals方法的比较 大多数时候(也许95%的时间)我将字符串与JavaString类的equals方法进行比较,如下所示:

if (string1.equals(string2))

此String equals方法查看两个Java字符串,如果它们包含完全相同的字符串,则认为它们相等。

看一个使用equals方法的快速String比较示例,如果运行以下测试,两个字符串将不被视为相等,因为字符不完全相同(字符的大小写不同):

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:JavaString与compareTo方法的比较

还有第三种比较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语言在基础JavaObject类中包含一个equals方法。每当你创建自己的对象并且你想提供一种方法来查看对象的两个实例是否“相等”时,你应该覆盖(并实现)类中的这个equals方法(就像Java语言在String equals方法中提供这种相等/比较行为一样)。

你可能想看看这个==,. equals(), compareTo(),和比较()

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

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

  • 案例1

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

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

  • 案例2

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

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

如果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(),每次都会创建一个新对象。

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

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

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

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