Разница между методами String#equals и String#contentEquals
В чем разница между String#equals
метод и String#contentEquals
метод?
10 ответов
String#equals()
не только сравнивает содержимое строки, но также проверяет, является ли другой объект также экземпляром 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 создания специальной реализации для строк вequals()
метод StringBuffer, StringBuilder и CharSequence, а также. Это было бы беспорядок.
И вот тогда String.contentEquals
приходит. Это автономный метод, который не должен следовать строгим требованиям и правилам для Object.equals
, Таким образом, вы можете более свободно реализовать смысл "равного содержания". Это позволяет вам делать интеллектуальные сравнения, например, между StringBuffer и String.
И сказать, в чем именно разница:
String.contentEquals()
можно сравнить содержимоеString
,StringBuilder
,StringBuffer
,CharSequence
и все производные классы из них. Если параметр имеет тип String, тоString.equals()
быть казненным.String.equals()
сравнивает только строковые объекты. Все остальные типы объектов считаются не равными.String.contentEquals()
можно сравнитьStringBuffer
а такжеStringBuilder
в интеллектуальном смысле. Это не вызывает тяжелыйtoString()
метод, который копирует весь контент в новый объект String. Вместо этого он сравнивается с основнымchar[]
массив, что здорово.
Этот ответ уже был опубликован dbw, но он удалил его, но у него были очень веские баллы для разницы при сравнении времени выполнения, какие исключения выбрасываются,
Если вы посмотрите на исходный код String#equals и String#contentEquals, то станет ясно, что существует два переопределенных метода для String#contentEquals
тот, который берет StringBuilder
и другие CharSequence
,
Разница между ними,
String#contentEquals
скинет NPE, если заданный аргументnull
ноString#equals
вернусьfalse
String#equals
сравнивает содержимое только тогда, когда предоставленный аргументinstance of String
в противном случае он вернетсяfalse
во всех остальных случаях, но с другой стороныString#contentEquals
проверяет содержимое всех объектов, которые реализуют интерфейсCharSequence
,Вы также можете настроить код так, чтобы
String#contentEquals
вернуть неправильный результат или результат, который вы хотите, переопределивequals
метод аргумента передается как показано ниже, но вы не можете сделать эти настройки сString#equals
,
Ниже код всегда будет выдаватьtrue
покаs
содержит любойstring
длиной 3 символа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; } }));
String#contentEquals
будет медленнееString#Equals
в случае, когда аргумент предоставленinstance of String
и длина обоихString
то же самое, но содержимое не равно.
Пример, если строкаString s = "madam"
а такжеString argPassed = "madan"
затемs.contentEquals(argPassed)
займет в два раза больше времени выполнения в этом случае по сравнению сs.equals(argPassed)
Если длина содержимого не одинакова для обеих строк, то функция
String#contentEquals
будет иметь лучшую производительность, чемString#Equals
почти во всех возможных случаях.
Еще один момент, чтобы добавить к его ответу
String#contentEquals
изString
Объект также будет сравниваться сStringBuilder
содержание и обеспечить соответствующий результат, аString#Equals
вернусьfalse
String
учебный классequals(Object o)
метод делает толькоString
сравнение. НоcontentEquals(CharSequence cs)
проверки на классы расширяютсяAbstractStringBuilder
т.е.StringBuffer
,StringBuilder
а такжеString
класс также (Все они имеют типCharSequence
).String str = "stackru"; StringBuilder builder = new StringBuilder(str); System.out.println(str.equals(builder)); System.out.println(str.contentEquals(builder));
выход:
false
true
Выход первого stmt false
так как builder
не тип String
так equals()
возвращается false
но contentEquals()
проверяет содержимое всего типа, как StringBuilder
, StringBuffer
, String
и, как содержание то же самое, следовательно, true
,
contentEquals
будет бросатьNullPointerException
если предоставленный аргументnull
ноequals()
вернет false, потому что equals() проверяет instanceOf (if (anObject instance of String)
) который возвращает false, если аргументnull
,
contentEquals(CharSequence cs)
:
- Позволяет проверить равенство заданного строкового значения любому экземпляру реализации интерфейса
java.lang.CharacterSequence
(например,CharBuffer
,Segment
,String
,StringBuffer
,StringBuilder
)
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);
}
}
equals()
а также contentEquals()
are two methods in String
class to compare two strings
а также string
с StringBuffer
,
Параметры contentEquals()
являются StringBuffer
а также String(charSequence)
, equals()
используется для сравнения двух strings
а также contentEquals()
is used to compare the contents of String
а также StringBuffer
,
метод contentEquals
а также equals
являются
public boolean contentEquals(java.lang.StringBuffer);
public boolean contentEquals(java.lang.CharSequence);
public boolean equals(Object o)
Here is an code which describes both methods
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, он сравнивает содержимое символ за символом. Возвращает true, если содержимое обоих строковых объектов одинаково.
String # contentEquals принимает интерфейс CharSequence в качестве аргумента. CharSequence может быть реализован двумя способами: с помощью i) класса String или (ii) AbstractStringBuilder(родительский класс StringBuffer, StringBuilder)
В contentEquals() длина сравнивается перед проверкой любого экземпляра объекта. Если длина одинакова, то проверяется, является ли объект аргумента экземпляром AbstractStringBuilder или нет. Если это так (т.е. StringBuffer или StringBuilder), то содержимое проверяется посимвольно. Если аргумент является экземпляром объекта String, то String#equals вызывается из String#contentEquals.
Короче говоря,
String#equals сравнивает содержимое символ за символом в случае, если аргумент также является объектом String. И String#contentEquals сравнивает содержимое в случае, если аргумент объекта реализует интерфейс CharSequence.
String#contentEquals работает медленнее, если мы сравниваем два строковых содержимого одинаковой длины, так как String#contentEquals внутренне вызывает String#equals для объекта String.
Если мы попытаемся сравнить объекты с разной длиной содержимого (скажем, "abc" с "abcd"), то String#contentEquals быстрее, чем String # равно. Потому что длина сравнивается перед проверкой экземпляра объекта.
Кстати, историческая причина разницы в том, что String изначально не имел суперкласса, поэтому String.equals() принимает String в качестве аргумента. Когда CharSequence был представлен как суперкласс String, он нуждался в собственном тесте на равенство, который работал бы во всех реализациях CharSequence, и который не вступал бы в конфликт с equals (), уже используемым String... поэтому мы получили CharSequence.contentEquals(), который наследуется String.
Если бы 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): верно
str1.contentEquals(str2): правда
str1.equals (str3): ложь
str1.contentEquals(str3): правда