Jaka jest różnica między tą String#equals
metodą a String#contentEquals
metodą?
Jaka jest różnica między tą String#equals
metodą a String#contentEquals
metodą?
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 equals
sprawdzania dokładnego dopasowania typu zStrings
(inne klasy mogą być luźniejsze z typami w swoich equals
metodach) .
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:
equals
Metoda 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.contentEquals
przychodzi 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 CharSequence
i 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ć StringBuffer
i StringBuilder
w 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#contentEquals
jednej, która bierze, StringBuilder
a druga CharSequence
.
Różnica między nimi,
String#contentEquals
wyrzuci NPE, jeśli podany argument jest, null
ale String#equals
zwrócifalse
String#equals
porównuje zawartość tylko wtedy, gdy podany argument jest instance of String
inaczej, zwróci false
we wszystkich innych przypadkach, ale z drugiej strony String#contentEquals
sprawdza zawartość wszystkich obiektów, które implementują interfejs CharSequence
.Możesz również zmodyfikować kod tak, aby String#contentEquals
zwracał niewłaściwy wynik lub wynik, nadpisując equals
metodę 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 s
zawierał dowolny, string
któ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#contentEquals
będzie wolniejszy niż String#Equals
w przypadku, gdy podany argument to instance of String
i długość obu String
jest 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#contentEquals
będzie miała lepszą wydajność niż String#Equals
w prawie wszystkich możliwych przypadkach.
Jeszcze jeden punkt do jego odpowiedzi
String#contentEquals
z String
obiektu będzie również porównać do StringBuilder
zawartości i zapewnić odpowiedni wynik while String#Equals
powrócifalse
String
class equals(Object o)
robi tylko String
porównanie. Ale contentEquals(CharSequence cs)
sprawdza klasy rozszerza AbstractStringBuilder
ie StringBuffer
, StringBuilder
a String
takż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 false
ponieważ builder
nie jest typu String
więc equals()
powraca false
ale contentEquals()
sprawdza zawartość wszystkich rodzaju jak StringBuilder
, StringBuffer
, String
i jako zawartość jest taka sama stąd true
.
contentEquals
wyrzuci, NullPointerException
jeśli podany argument to, null
ale 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 String
klasie, aby porównać dwa strings
i string
z StringBuffer
.
Parametry contentEquals()
są StringBuffer
i String(charSequence)
. equals()
służy do porównywania dwóch strings
i contentEquals()
służy do porównywania zawartości String
i StringBuffer
.
Metoda contentEquals
i equals
są
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
, StringBuffer
itp 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?