String#equals和String#contentEquals方法之间的区别


Answers:


171

String#equals()不是只有在其他对象也是一个实例比较字符串的内容,而且检查String。在String#contentEquals()只比较的内容(字符序列)和不检查其他对象也是的一个实例String。它可以是任何东西,只要它是一个实现CharSequence覆盖AO StringStringBuilderStringBufferCharBuffer,等。


12
因此,它类似于javascript中的运算符==(contentEquals)和===(equals)吗?
anestv

2
@anestv在Java中,==运算符将只允许您比较引用而不是两个对象的内容
斯蒂芬

2
@Alex进行澄清,Java中的==运算符用于检查两个对象是否指向内存中的同一位置,或者两个原始类型(字节,短整数,整型,长整数,浮点型,双精度型,字符型,布尔型)是否相等。
La-comadreja

2
@Stephan,==提到的只是JavaScript;关于Java从来没有提到过。
Olathe

@anestv等方面存在差异(==在JavaScript远高于宽松contentEquals,这不会触及数,例如),但你即将正确equals的确切类型匹配检查Strings(其他类可能是他们的宽松有型equals的方法) 。
Olathe

43

轻松地说:String.contentEquals()是的更聪明的兄弟String.equals(),因为它在实现中比可以更加自由String.equals()

有某些原因导致使用单独的String.contentEquals()方法。我认为最重要的原因是:

  • equals方法必须是自反的。这意味着:x.equals(y) == y.equals(x)。这意味着aString.equals(aStringBuffer)必须与相同aStringBuffer.equals(aString)。这将要求Java API开发人员也使用equals()StringBuffer,StringBuilder和CharSequence方法对String进行一些特殊的实现。这将是一团糟。

这就是String.contentEquals进来,这是一个独立的方法,它没有必须遵循严格的要求和规则Object.equals。这样,您可以更自由地实现“平等内容”的感觉。例如,这使您可以在StringBuffer和String之间进行智能比较。

再说一下到底有什么区别:

  • String.contentEquals()可以比较a String,a StringBuilder,a StringBuffer,a CharSequence和所有这些派生类的内容。如果参数的类型为String,则String.equals()执行该参数。

  • String.equals()仅比较String对象。所有其他对象类型均视为不相等。

  • String.contentEquals()可以比较StringBufferStringBuilder以一种智能的方式进行比较。它叫重toString()方法,其拷贝的全部内容到一个新的String对象。相反,它将与基础char[]数组进行比较,这很棒。


31

这个答案已经由dbw发布,但是他删除了,但是在比较执行时间,抛出什么异常,

如果您查看源代码String#equalsString#contentEquals,很明显,对于String#contentEquals一个方法take StringBuilder和另一个,有两种覆盖的方法CharSequence
他们之间的区别,

  1. String#contentEquals如果提供的参数为,将抛出NPE,nullString#equals返回false
  2. String#equals仅在提供的参数instance of String否则比较内容,否则false在所有其他情况下它都会返回,但另一方面String#contentEquals检查实现接口的所有对象的内容CharSequence
  3. 您还可以调整代码,以便String#contentEquals通过覆盖equals传递的参数的方法来返回错误的结果或所需的结果,如下所示,但是您不能使用进行这些调整String#equals。只要包含3个字符长的
    代码,下面的代码将始终产生truesstring

        String s= new String("abc");// "abc";
        System.out.println(s.contentEquals(new CharSequence() 
        {
    
            @Override
            public CharSequence subSequence(int arg0, int arg1) {
                // TODO Auto-generated method stub
                return null;
            }
    
            @Override
            public int length() {
                // TODO Auto-generated method stub
                return 0;
            }
    
            @Override
            public char charAt(int arg0) {
                // TODO Auto-generated method stub
                return 0;
            }
    
    
            @Override
            public boolean equals(Object obj) 
            {
               return true;
            }
        }));
  4. String#contentEqualsString#Equals在提供的参数为instance of String且两者的长度String相同但内容不相等的情况下会慢一些。
    例如,如果字符串为String s = "madam"and,String argPassed = "madan"那么s.contentEquals(argPassed)在这种情况下,与之相比,将花费几乎两倍的执行时间s.equals(argPassed)

  5. 如果两个字符串的内容长度都不相同,则函数String#contentEqualsString#Equals在几乎所有可能的情况下具有更好的性能。

还有一点要补充

  1. String#contentEquals一个的String对象也将比较的StringBuilder内容,同时提供相应的结果String#Equals将返回false

4
@dbw这个答案来自您发布的答案
Prateek

@dbw此外,您为什么仍然删除帖子?
MC Emperor

14
  • Stringequals(Object o)方法仅做String比较。但contentEquals(CharSequence cs)上课的检查延伸AbstractStringBuilder,即 StringBufferStringBuilderString类也(他们都是类型CharSequence)。

    String str = "stackoverflow";
    StringBuilder builder = new StringBuilder(str);
    System.out.println(str.equals(builder));
    System.out.println(str.contentEquals(builder));

输出:

false
true

first stmt的输出是false因为builder不是类型,String所以equals()返回,false而是contentEquals()检查所有类型的内容,例如StringBuilderStringBufferString并且由于内容相同,因此进行检查true

  • contentEqualsNullPointerException如果提供的参数为,则会抛出该错误,nullequals()将返回false,因为equals()检查instanceOf(if (anObject instance of String)),如果参数为,则返回false null

14

contentEquals(CharSequence cs)

  • 让你检查给出的字符串值的平等接口的任何实现的实例java.lang.CharacterSequence(例如CharBufferSegmentStringStringBufferStringBuilder

equals(Object anObject)

  • 让你检查给出的字符串值的平等类型的任何实例java.lang.String

RTFC :)

由于阅读源代码是理解它的最佳方式,因此我将分享这两种方法的实现(自jdk 1.7.0_45起)

public boolean contentEquals(CharSequence cs) {
    if (value.length != cs.length())
        return false;
    // Argument is a StringBuffer, StringBuilder
    if (cs instanceof AbstractStringBuilder) {
        char v1[] = value;
        char v2[] = ((AbstractStringBuilder) cs).getValue();
        int i = 0;
        int n = value.length;
        while (n-- != 0) {
            if (v1[i] != v2[i])
                return false;
            i++;
        }
        return true;
    }
    // Argument is a String
    if (cs.equals(this))
        return true;
    // Argument is a generic CharSequence
    char v1[] = value;
    int i = 0;
    int n = value.length;
    while (n-- != 0) {
        if (v1[i] != cs.charAt(i))
            return false;
        i++;
    }
    return true;
}

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String) anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                        return false;
                i++;
            }
            return true;
        }
    }
    return false;
 }

还有另一个String#contentEquals()方法:

public boolean contentEquals(StringBuffer sb) {
    synchronized(sb) {
        return contentEquals((CharSequence)sb);
    }
}

9

equals()contentEquals()两种方法在String类比较两个stringsstringStringBuffer

的参数contentEquals()StringBufferString(charSequence)equals()用于比较两个stringscontentEquals()用于比较的内容StringStringBuffer

方法contentEqualsequals

public boolean contentEquals(java.lang.StringBuffer);
public boolean contentEquals(java.lang.CharSequence);
public boolean equals(Object o)

这是描述两种方法的代码

public class compareString {
    public static void main(String[] args) {
        String str1 = "hello";    
        String str2 = "hello";

        StringBuffer sb1 = new StringBuffer("hello");
        StringBuffer sb2 = new StringBuffer("world");

        boolean result1 = str1.equals(str2);        // works nice and returns true
        System.out.println(" str1.equals(str2) - "+ result1);

        boolean result2 = str1.equals(sb1);         // works nice and returns false
        System.out.println(" str1.equals(sb1) - "+ result2);

        boolean result3 = str1.contentEquals(sb1);  // works nice and returns true
        System.out.println(" str1.contentEquals(sb1) - "+ result3);

        boolean result4 = str1.contentEquals(sb2);  // works nice and returns false
        System.out.println(" str1.contentEquals(sb2) - "+ result4);

        boolean result5 = str1.contentEquals(str2);  // works nice and returns true
        System.out.println(" str1.contentEquals(str2) - "+ result5);
    }
}

输出:

 str1.equals(str2) - true
 str1.equals(sb1) - false
 str1.contentEquals(sb1) - true
 str1.contentEquals(sb2) - false
 str1.contentEquals(str2) - true

7

String#equals将Object作为参数,并检查其是否为String对象的实例。如果参数对象是字符串对象,则它将逐字符比较内容。如果两个字符串对象的内容相同,则返回true。

String#contentEquals将CharSequence接口作为参数。CharSequence可以通过两种方式实现-通过使用i)字符串类或(ii)AbstractStringBuilder(StringBuffer,StringBuilder的父类)

contentEquals() 中,将在检查任何对象实例之前比较长度。如果长度相同,则检查参数对象是否为AbstractStringBuilder的实例。如果是这样(即StringBuffer或StringBuilder),则将逐字符检查内容。如果参数是String对象的实例,则从String#contentEquals调用String#equals。

简而言之,

如果参数也是String对象,则String#equals逐字符比较内容。如果参数对象实现CharSequence接口,则String#contentEquals比较内容。

如果我们比较两个相同长度的字符串内容,因为String#contentEquals内部调用String#equals作为String对象,则String#contentEquals速度会变慢。

如果我们尝试比较内容长度不同的对象(例如“ abc”与“ abcd”),则String#contentEquals比String#equals更快。因为长度是在任何对象实例检查之前进行比较的。


6

contentEquals()方法检查是内容是相同的之间StringStringBuffer等等,其某种字符序列。


5

顺便说一句,造成这种差异的历史原因是String最初没有超类,因此String.equals()将String作为其参数。当CharSequence作为String的超类引入时,它需要自己的一个相等性测试,该测试适用于所有CharSequence实现,并且不会与String已经使用的equals()发生冲突……因此我们得到了CharSequence.contentEquals( ),由String继承。

如果Java 1.0中已经存在CharSequence,则我们可能只具有CharSequence.equals(),而String会简单地实现它。

啊,不断发展的语言所带来的乐趣...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.