Jaka jest różnica między tą String#equalsmetodą a String#contentEqualsmetodą?
Jaka jest różnica między tą String#equalsmetodą a String#contentEqualsmetodą?
Odpowiedzi:
String#equals()Porównuje nie tylko treść napisu, ale także sprawdza, czy inny obiekt jest instancją String. String#contentEquals()Porównuje tylko zawartość (sekwencja znaków) i czy nie sprawdzić, czy inny obiekt jest instancją String. Może to być coś tak długo, jak jest to realizacja CharSequence, która obejmuje ao String, StringBuilder, StringBuffer, CharBuffer, itd.
==operator zezwala tylko na porównywanie odniesień, a nie zawartości dwóch obiektów.
==wspomniany jest tylko JavaScript; nigdy nie wspomniano o Javie.
==w JavaScript jest znacznie luźniejsze niż contentEquals, na przykład nie zmieniają liczb), ale masz rację co do equalssprawdzania dokładnego dopasowania typu zStrings (inne klasy mogą być luźniejsze z typami w swoich equalsmetodach) .
Mówiąc prościej: String.contentEquals()jest mądrzejszym bratem String.equals(), ponieważ może być bardziej swobodny w implementacji niż String.equals().
Istnieje kilka powodów, dla których istnieje oddzielna String.contentEquals()metoda. Myślę, że najważniejszym powodem jest:
equalsMetoda musi być refleksyjny. Oznacza to, że: x.equals(y) == y.equals(x). Oznacza to, że aString.equals(aStringBuffer)musiałoby to być to samo, co aStringBuffer.equals(aString). Wymagałoby to od programistów Java API wykonania specjalnej implementacji dla Strings w equals()metodzie StringBuffer, StringBuilder i CharSequence. To byłby bałagan.To jest, gdy String.contentEqualsprzychodzi w. Jest to metoda samodzielna że ma nie muszą przestrzegać surowych wymogów i zasad dla Object.equals. W ten sposób można swobodniej realizować poczucie „równej treści” . Pozwala to na przykład na dokonywanie inteligentnych porównań między StringBuffer i String.
I powiedzieć, na czym dokładnie polega różnica:
String.contentEquals()potrafi porównać zawartość a String, a StringBuilder, a StringBuffer, a CharSequencei wszystkich ich klas pochodnych. Jeśli parametr jest typu String, String.equals()wykonaj polecenie.
String.equals()porównuje tylko obiekty typu String. Wszystkie inne typy obiektów są uważane za nierówne.
String.contentEquals()potrafi porównać StringBufferi StringBuilderw inteligentny sposób. Robi nie wywołać ciężkie toString()metoda, która kopiuje całą zawartość do nowego obiektu String. Zamiast tego porównuje się z podstawową char[]tablicą, co jest świetne.
Ta odpowiedź została już opublikowana przez dbw, ale usunął ją, ale miał kilka bardzo ważnych punktów za różnicę, porównując czas wykonania, jakie wyjątki są wyrzucane,
Jeśli spojrzysz na kod źródłowy String # equals i String # contentEquals , jasne jest, że istnieją dwie nadpisane metody dla String#contentEqualsjednej, która bierze, StringBuildera druga CharSequence.
Różnica między nimi,
String#contentEqualswyrzuci NPE, jeśli podany argument jest, nullale String#equalszwrócifalseString#equalsporównuje zawartość tylko wtedy, gdy podany argument jest instance of Stringinaczej, zwróci falsewe wszystkich innych przypadkach, ale z drugiej strony String#contentEqualssprawdza zawartość wszystkich obiektów, które implementują interfejs CharSequence.Możesz również zmodyfikować kod tak, aby String#contentEqualszwracał niewłaściwy wynik lub wynik, nadpisując equalsmetodę przekazanego argumentu, jak pokazano poniżej, ale nie możesz zrobić tych poprawek String#equals.
Poniższy kod zawsze będzie produkowaćtrue tak długo, jak będzie szawierał dowolny, stringktóry ma 3 znaki
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#contentEqualsbędzie wolniejszy niż String#Equalsw przypadku, gdy podany argument to instance of Stringi długość obu Stringjest taka sama, ale zawartość nie jest równa.
Przykład, jeśli ciąg jest, String s = "madam"a String argPassed = "madan"następnie s.contentEquals(argPassed)zajmie prawie dwukrotnie czas wykonania w tym przypadku w porównaniu zs.equals(argPassed)
Jeśli długość treści nie jest taka sama dla obu ciągów, funkcja String#contentEqualsbędzie miała lepszą wydajność niż String#Equalsw prawie wszystkich możliwych przypadkach.
Jeszcze jeden punkt do jego odpowiedzi
String#contentEqualsz Stringobiektu będzie również porównać do StringBuilderzawartości i zapewnić odpowiedni wynik while String#Equalspowrócifalse Stringclass equals(Object o)robi tylko Stringporównanie. Ale contentEquals(CharSequence cs)sprawdza klasy rozszerza AbstractStringBuilderie StringBuffer, StringBuildera Stringtakże klasę (wszystkie są typu CharSequence).
String str = "stackoverflow";
StringBuilder builder = new StringBuilder(str);
System.out.println(str.equals(builder));
System.out.println(str.contentEquals(builder));wynik:
false
true
Wyjście pierwszego instr jest falseponieważ buildernie jest typu Stringwięc equals()powraca falseale contentEquals()sprawdza zawartość wszystkich rodzaju jak StringBuilder, StringBuffer, Stringi jako zawartość jest taka sama stąd true.
contentEqualswyrzuci, NullPointerExceptionjeśli podany argument to, nullale equals()zwróci false, ponieważ equals () sprawdza instancję instanceOf ( if (anObject instance of String)), która zwraca false, jeśli argumentem jest null.contentEquals(CharSequence cs):
java.lang.CharacterSequence(na przykład CharBuffer, Segment, String, StringBuffer, StringBuilder)equals(Object anObject):
java.lang.String tylkoRTFC :)
Ponieważ odczytanie źródła jest najlepszym sposobem na jego zrozumienie, udostępniam implementacje obu metod (od 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;
}
Istnieje inna metoda String # contentEquals ():
public boolean contentEquals(StringBuffer sb) {
synchronized(sb) {
return contentEquals((CharSequence)sb);
}
}
equals()i contentEquals()są dwie metody w Stringklasie, aby porównać dwa stringsi stringz StringBuffer.
Parametry contentEquals()są StringBufferi String(charSequence). equals()służy do porównywania dwóch stringsi contentEquals()służy do porównywania zawartości Stringi StringBuffer.
Metoda contentEqualsi equalssą
public boolean contentEquals(java.lang.StringBuffer);
public boolean contentEquals(java.lang.CharSequence);
public boolean equals(Object o)
Oto kod, który opisuje obie metody
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);
}
}
Wynik:
str1.equals(str2) - true
str1.equals(sb1) - false
str1.contentEquals(sb1) - true
str1.contentEquals(sb2) - false
str1.contentEquals(str2) - true
String # equals przyjmuje Object jako argument i sprawdza, czy jest wystąpieniem obiektu String, czy nie. Jeśli obiekt argumentu to String Object, wówczas porównuje zawartość znak po znaku. Zwraca prawdę w przypadku, gdy zawartość obu obiektów łańcuchowych jest taka sama.
String # contentEquals przyjmuje interfejs CharSequence jako argument. CharSequence można zaimplementować na 2 sposoby - przy użyciu i) klasy String lub (ii) AbstractStringBuilder (klasa nadrzędna StringBuffer, StringBuilder)
W metodzie contentEquals () długość jest porównywana przed jakimkolwiek sprawdzeniem instancji obiektu. Jeśli długość jest taka sama, sprawdza, czy argument object jest instancją AbstractStringBuilder, czy nie. Jeśli tak jest (np. StringBuffer lub StringBuilder), zawartość jest sprawdzana znak po znaku. W przypadku, gdy argument jest instancją obiektu String, wówczas String # równa się wywoływana z String # contentEquals.
Krótko mówiąc,
String # equals porównuje zawartość znak po znaku w przypadku, gdy argument jest również obiektem String. A String # contentEquals porównuje zawartość w przypadku, gdy obiekt argumentu implementuje interfejs CharSequence.
String # contentEquals jest wolniejsze w przypadku, gdy porównujemy dwie treści typu string o tej samej długości, co String # contentEquals wewnętrznie wywołuje String # equals dla obiektu String.
W przypadku, gdy próbujemy porównać obiekty o różnej długości zawartości (powiedzmy „abc” z „abcd”), wtedy String # contentEquals jest szybszy niż String # equals. Ponieważ długość jest porównywana przed jakimkolwiek sprawdzaniem instancji obiektu.
Do contentEquals()kontroli sposobu jest zawartość jest taka sama między String, StringBufferitp niektóre rodzaj sekwencji char.
Przy okazji, historycznym powodem tej różnicy jest to, że String pierwotnie nie miał nadklasy, więc String.equals () przyjmuje String jako argument. Kiedy CharSequence został wprowadzony jako nadklasa String, potrzebował własnego testu równości, który działałby we wszystkich implementacjach CharSequence i który nie kolidowałby z equals () już używanym przez String ... więc otrzymaliśmy CharSequence.contentEquals ( ), który jest dziedziczony przez String.
Gdyby CharSequence był obecny w Javie 1.0, prawdopodobnie mielibyśmy tylko CharSequence.equals (), a String po prostu by to zaimplementował.
Ach, radość z rozwijających się języków ...
==(contentEquals) i===(equals) w javascript?