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

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

String#equals()不仅比较String的内容,还检查另一个对象是否也是String一个实例。 String#contentEquals()只比较内容(字符序列),并不检查另一个对象是否也是String一个实例。 它可以是任何东西,只要它是一个CharSequence的实现,它涵盖了StringStringBuilderStringBufferCharBuffer等等。

简单地说: String.contentEquals()String.equals()更聪明的兄弟,因为它可以比String.equals()更加自由。

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

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

所以,这就是当String.contentEquals进来。这是一个独立的方法 ,不必遵循 Object.equals 严格的要求和规则 。 这样可以更自由地实现“相等内容”的意义。 例如,这允许您在StringBuffer和String之间进行智能比较。

并说出究竟有什么不同之处:

  • String.contentEquals()可以比较StringStringBuilderStringBufferCharSequence及其所有派生类的内容。 如果参数的types是String,那么String.equals()会被执行。

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

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

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

如果你看看源代码String#equals和String#contentEquals,那么显然String#contentEquals有两个重载方法,一个是StringBuilder和其他CharSequence
他们之间的区别,

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

      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会比较慢, String#Equals在提供的参数是instance of String并且两个String的长度相同但内容不相等的情况下。
    如果string是String s = "madam"String argPassed = "madan"那么与s.equals(argPassed)相比,在这种情况下s.contentEquals(argPassed)将执行几乎两倍的执行时间。

  5. 如果两个string的内容长度不相同,那么函数String#contentEquals在几乎所有可能的情况下都会有更好的性能,然后String#Equals

还有一点要补充他的答案

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

contentEquals(CharSequence cs)

  • 让您检查给定的string值与接口java.lang.CharacterSequence (例如, CharBufferSegmentStringStringBufferStringBuilder )的任何实现实例的相等性。

equals(Object anObject)

  • 让您检查给定的string值与任何只有 java.lang.Stringtypes的实例的相等性

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)检查类是否扩展了AbstractStringBuilderStringBufferStringBuilderString类(它们都是CharSequencetypes)。

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

输出:

 false true 

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

  • 如果提供的参数为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 

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

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

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

contentEquals()中比较任何对象实例检查前的长度。 如果长度相同,则检查参数对象是否是AbstractStringBuilder的实例。 如果是这样的话(即StringBuffer或者StringBuilder),那么内容将被逐个检查。 如果参数是String对象的一个​​实例,则String#等于从String#contentEquals中调用。

所以总之,

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

如果我们比较两个相同长度的string内容作为String#contentEquals在内部调用String#equals为String对象,则String#contentEquals会更慢。

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

顺便说一句,不同的历史原因是String最初没有超类,所以String.equals()接受一个string作为它的参数。 当CharSequence作为String的超类引入时,它需要一个在所有CharSequence实现中工作的自己的等式testing,并且不会和String已经使用的equals()相冲突…所以我们得到了CharSequence.contentEquals( ),它由Stringinheritance。

如果CharSequence已经存在于Java 1.0中,我们只会使用CharSequence.equals()和String来实现它。

啊,不断发展的语言的乐趣…

最大的区别是equals()只能用于另一个string,而contentEquals()可以用于任何CharacterSequence(如StringBuilder)。

 public class Test{ public static void main(String[] args) { String str1 = "Hello"; String str2 = new String("Hello"); StringBuilder str3 = new StringBuilder(str1); System.out.println("str1.equals(str2): " + (str1.equals(str2))); System.out.println("str1.contentEquals(str2): " + (str1.contentEquals(str2))); System.out.println("str1.equals(str3): " + (str1.equals(str3))); System.out.println("str1.contentEquals(str3): " + (str1.contentEquals(str3))); }} 

将输出为

str1.equals(str2):true

str1.contentEquals(str2):true

str1.equals(str3):false

str1.contentEquals(str3):true