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

String#equals方法和 String#contentEquals方法的区别是什么?

70525 次浏览

String#equals()不仅比较 String 的内容,还检查另一个对象是否也是 String的实例。String0只比较内容(字符序列) ,并且 String1检查另一个对象是否也是 String的实例。它可以是任何东西,只要它是涵盖 A.o.String3、 String4、 String5、 String6等的 String2的实现。

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

返回文章页面

  • 允许您使用接口 java.lang.CharacterSequence的任何实现实例(例如,CharBufferSegmentStringStringBufferStringBuilder)检查给定字符串值的相等性

返回文章页面

  • 允许您检查给定字符串值与 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);
}
}
  • 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));
    

output:

false
true

第一个 stmt 的输出是 false,因为 builder不是 String类型,所以 equals()返回 false,但是 contentEquals()检查所有类型的内容,比如 StringBuilderStringBufferString,因为内容是相同的,所以是 true

  • 如果提供的参数是 null,则 contentEquals将抛出 NullPointerException,但是 equals()将返回 false,因为 equals ()检查 instanceOf (if (anObject instance of String)) ,如果参数是 null,则返回 false。

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

简单地说: ABC0是 String.equals()更聪明的兄弟,因为它在实现中可以比 String.equals()更自由。

有一些原因,为什么有一个单独的 String.contentEquals()方法。最重要的原因,我认为是:

  • equals方法必须是自反的。这意味着: x.equals(y) == y.equals(x)。这意味着 aString.equals(aStringBuffer)必须与 aStringBuffer.equals(aString)相同。这将需要 JavaAPI 开发人员为 StringBuffer、 StringBuilder 和 CharSequence 的 equals()方法中的 String 制作一些特殊的实现。这将是一个烂摊子。

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

我想说的是:

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

  • String.equals()只比较字符串对象。所有其他对象类型被认为是不相等的。

  • String.contentEquals()可以对 StringBufferStringBuilder进行智能比较。它确实调用了重 toString()方法,将整个内容复制到一个新的 String 对象。相反,它与底层的 char[]数组进行了比较,这非常好。

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

如果查看源代码 字符串 # = 字符串 # contentEquals,很明显有两个重写的 String#contentEquals方法,一个采用 StringBuilder,另一个采用 CharSequence
他们之间的区别,

  1. 如果提供的参数是 null,那么 String#contentEquals将抛出 NPE,但是 String#equals将返回 false
  2. 只有当提供的参数是 instance of String时,String#equals才会比较内容,否则在所有其他情况下它将返回 false,但另一方面 String#contentEquals检查所有实现接口 CharSequence的对象的内容。
  3. 您还可以调整代码,使 String#contentEquals通过覆盖下面所传递的参数的 equals方法返回您想要的错误结果或结果,但是您不能对 String#equals进行这些调整。
    下面的代码总是产生 true ,只要 s包含任何3个字符长的 string

        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#contentEquals will be slower then String#Equals in the case when argument supplied is instance of String and the length of both String is same but contents are not equal.
    Example if the string are String s = "madam" and String argPassed = "madan" then s.contentEquals(argPassed) will take almost double execution time in this case as compared to s.equals(argPassed)

  5. If the content length are not same for both the strings then function String#contentEquals will have better performance then String#Equals in almost all possible cases.

One more point to add to his answer

  1. String#contentEquals of a String object will also compare to the StringBuilder contents and provide the appropriate result while String#Equals will return false

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

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

进化语言的乐趣。

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

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

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

简而言之,

字符串 # equals 逐字符比较内容参数也是字符串对象的情况。字符串 # contentEquals比较了 case 参数对象实现 CharSequence 接口时的内容。

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

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