首页 文章

如何比较Java中的字符串?

提问于
浏览
727

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

== 不好吗?什么时候应该不应该使用?有什么不同?

23 回答

  • 96

    我同意zacherates的答案 .

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

    从zacherates示例:

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

    如果你实习非文字字符串相等是 true

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

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

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

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

    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
    
  • 95

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

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

    ==运算符检查两个字符串是否完全相同 . .equals()方法检查两个字符串是否具有相同的值 .

  • 37

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

    equals() 方法将检查2个对象的 contentsstates 是否相同 .

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

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

    不要担心性能 . 有些事情要鼓励使用 String.equals()

    • String.equals() 的实现首先检查引用相等性(使用 == ),如果2个字符串通过引用相同,则不再执行进一步的计算!

    • 如果2个字符串引用不相同, String.equals() 将接下来检查字符串的长度 . 这也是一个快速操作,因为 String 类存储字符串的长度,不需要计算字符或代码点 . 如果长度不同,不再进行进一步检查,我们知道它们不能相等 .

    • 只有当我们到达这一点时才会实际比较2个字符串的内容,这将是一个简短的比较:如果我们找到不匹配的字符(在2中的相同位置),不会比较所有字符字符串),不会检查其他字符 .

    完成所有操作后,即使我们保证字符串是实习生,使用 equals() 方法仍然不是人们可能认为的开销,绝对是推荐的方法 . 如果您想要有效的引用检查,那么使用枚举,语言规范和实现保证相同的枚举值将是同一个对象(通过引用) .

  • 409

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

  • 48

    == compares object references in JavaString 对象也不例外 .

    For comparing the actual contents of objects (including String), one must use the equals method .

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

  • 74

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

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

    Option 1: Java String comparison with the equals method 大部分时间(可能是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.")
    }
    

    Option 2: String comparison with the equalsIgnoreCase method

    在一些字符串比较测试中,您将要忽略字符串是大写还是小写 . 如果要以不区分大小写的方式测试字符串是否相等,请使用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.")
     }
    

    Option 3: Java String comparison with the compareTo method

    还有第三种,不太常见比较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()

  • 90

    功能:

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

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

  • 41

    运算符==始终用于 object reference comparison ,而字符串类.equals()方法为 content comparison 重写:

    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)
    
  • 120

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

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

  • 37

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

    .equals() 测试值的相等性(它们是否逻辑"equal") .

    Objects.equals()在调用 .equals() 之前检查 null ,因此您不必(从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
    

    你几乎 always 想要使用 Objects.equals() . 在 rare 情况下,您处理interned字符串 know ,您可以使用 == .

    来自JLS 3.10.5. String Literals

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

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

  • 79
    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" . 引用不同,但内容相同 .

  • 69

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

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

  • 44

    == 比较对象引用 .

    .equals() 比较字符串值 .

    有时 == 会给出比较字符串值的幻想,如下列情况:

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

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

    (a==b) ===> true

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

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

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

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

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

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

  • 35

    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实例 . 否则你会遇到错误 .

  • 5156

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

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

  • 115

    == 测试对象引用, .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";
    

    But beware of nulls!

    == 处理 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"));
    
  • 210

    如果 equals() 类中存在 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() 每次都会创建一个新对象 .

  • 137

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

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

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

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

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

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

  • 654

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

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

    Equals为您进行真正的比较 .

  • 93

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

  • 159

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

    如果两个对象(不是关于PRIMITIVES的对话)指向SAME对象实例,则 == 返回true . 如果两个对象包含相同的数据 .equals() 则返回true equals() Versus == in Java

    这可能对你有帮助 .

相关问题