String#equals和String#contentEquals方法之间的区别
String#equals方法和String#contentEquals方法有什么区别?
String#equals()不仅比较String的内容,还检查另一个对象是否也是String一个实例。 String#contentEquals()只比较内容(字符序列),并不检查另一个对象是否也是String一个实例。 它可以是任何东西,只要它是一个CharSequence的实现,它涵盖了String , StringBuilder , StringBuffer , CharBuffer等等。
简单地说: 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()可以比较String,StringBuilder,StringBuffer,CharSequence及其所有派生类的内容。 如果参数的types是String,那么String.equals()会被执行。 -
String.equals()只比较String对象。 所有其他对象types被认为是不相等的。 -
String.contentEquals()可以智能地比较StringBuffer和StringBuilder。 它不会调用繁重的toString()方法,将整个内容复制到一个新的String对象中。 相反,它与底层的char[]数组进行比较,这非常棒。
这个答案已经被dbw发布了,但是他被删除了,但是他在比较执行时间,抛出了什么exception,
如果你看看源代码String#equals和String#contentEquals,那么显然String#contentEquals有两个重载方法,一个是StringBuilder和其他CharSequence 。
他们之间的区别,
- 如果提供的参数为
null则String#contentEquals将抛出NPE,但String#equals将返回false -
String#equals仅当提供的参数是instance of String时才比较内容instance of String否则在所有其他情况下将返回false,但另一方面,String#contentEquals检查实现接口CharSequence的所有对象的CharSequence。 -
您还可以调整代码,以便
String#contentEquals通过覆盖传递参数的equals方法返回错误的结果或结果,但不能使用String#equals调整。
只要s包含任何长度为3个字符的string, 下面的代码将始终生成trueString 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; } })); -
String#contentEquals会比较慢,String#Equals在提供的参数是instance of String并且两个String的长度相同但内容不相等的情况下。
如果string是String s = "madam"和String argPassed = "madan"那么与s.equals(argPassed)相比,在这种情况下s.contentEquals(argPassed)将执行几乎两倍的执行时间。 -
如果两个string的内容长度不相同,那么函数
String#contentEquals在几乎所有可能的情况下都会有更好的性能,然后String#Equals。
还有一点要补充他的答案
- 一个
String对象的String#contentEquals也将与StringBuilder内容进行比较,并提供相应的结果,而String#Equals将返回false
contentEquals(CharSequence cs) :
- 让您检查给定的string值与接口
java.lang.CharacterSequence(例如,CharBuffer,Segment,String,StringBuffer,StringBuilder)的任何实现实例的相等性。
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); } }
-
String类equals(Object o)方法只做String比较。 但contentEquals(CharSequence cs)检查类是否扩展了AbstractStringBuilder即StringBuffer,StringBuilder和String类(它们都是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的内容,比如StringBuilder , StringBuffer , String ,因为内容是相同的。
- 如果提供的参数为
nullcontentEquals将抛出NullPointerException,但equals()将返回false,因为equals()会检查instanceOf(if (anObject instance of String)),如果参数为null,则返回false。
equals()和contentEquals()是String类中的两个方法,用于比较两个strings和string与StringBuffer 。
contentEquals()的参数是StringBuffer和String(charSequence) 。 equals()用于比较两个strings , contentEquals()用于比较String和StringBuffer的内容。
方法contentEquals和equals是
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()方法检查的内容是一个String , StringBuffer等之间的某种字符序列。
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