Różnica między metodami String # equals i String # contentEquals

Odpowiedzi:

171

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.

BalusC
źródło
12
Czy jest to więc podobne do operatorów ==(contentEquals) i ===(equals) w javascript?
anestv
2
@anestv W Javie ==operator zezwala tylko na porównywanie odniesień, a nie zawartości dwóch obiektów.
Stephan
2
@Alex, aby wyjaśnić, operator == w Javie służy do sprawdzania, czy dwa obiekty wskazują tę samą lokalizację w pamięci, czy też dwa typy pierwotne (bajt, krótki, int, long, float, double, char, boolean) są równe.
La-comadreja
2
@Stephan, ==wspomniany jest tylko JavaScript; nigdy nie wspomniano o Javie.
Olathe
@anestv, istnieją różnice ( ==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) .
Olathe
43

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.

Martijn Courteaux
źródło
31

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,

  1. String#contentEqualswyrzuci NPE, jeśli podany argument jest, nullale String#equalszwrócifalse
  2. String#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.
  3. 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;
            }
        }));
  4. 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)

  5. 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

  1. String#contentEqualsz Stringobiektu będzie również porównać do StringBuilderzawartości i zapewnić odpowiedni wynik while String#Equalspowrócifalse
Prateek
źródło
4
@dbw ta odpowiedź pochodzi z opublikowanej przez Ciebie odpowiedzi
Prateek
@dbw Poza tym, dlaczego mimo to usunąłeś swój post?
MC Emperor
14
  • 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.
Próbować
źródło
14

contentEquals(CharSequence cs):

  • Pozwala sprawdzić równość danej wartości ciąg z dowolnej instancji implementacja interfejsu java.lang.CharacterSequence(na przykład CharBuffer, Segment, String, StringBuffer, StringBuilder)

equals(Object anObject):

  • Pozwala sprawdzić równość danej wartości ciąg z dowolnej instancji typu java.lang.String tylko

RTFC :)

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);
    }
}
Amit Sharma
źródło
9

equals()i contentEquals()są dwie metody w Stringklasie, aby porównać dwa stringsi stringz StringBuffer.

Parametry contentEquals()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 equals

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
Asfab
źródło
7

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.

Anirban Pal
źródło
6

Do contentEquals()kontroli sposobu jest zawartość jest taka sama między String, StringBufferitp niektóre rodzaj sekwencji char.

fastcodejava
źródło
5

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 ...

keszlam
źródło