Unterschied zwischen den Methoden String # equals und String # contentEquals

Antworten:

171

Der String#equals()vergleicht nicht nur den Inhalt des Strings, sondern prüft auch, ob das andere Objekt ebenfalls eine Instanz von a ist String. Der String#contentEquals()vergleicht nur den Inhalt (die Zeichenfolge) und prüft nicht , ob das andere Objekt ebenfalls eine Instanz von ist String. Es kann alles sein , solange es eine Implementierung ist CharSequenceder deckt ua String, StringBuilder, StringBuffer, CharBufferetc.

BalusC
quelle
12
==Ist es also wie bei den Operatoren (contentEquals) und ===(equals) in Javascript?
Anästhesie
2
@anestv In Java erlaubt der ==Operator nur den Vergleich der Referenzen, nicht des Inhalts zweier Objekte.
Stephan
2
@Alex zur Verdeutlichung: Der Operator == in Java dient zur Überprüfung, ob zwei Objekte auf dieselbe Position im Speicher verweisen oder ob zwei primitive Typen (Byte, Short, Int, Long, Float, Double, Char, Boolean) gleich sind.
La-Comadreja
2
@Stephan, das ==erwähnte ist nur JavaScript; Es wird nie in Bezug auf Java erwähnt.
Olathe
@anestv gibt es Unterschiede ( ==in JavaScript ist weit lockerer als contentEquals, die Zahlen zum Beispiel nicht berühren,), aber Sie haben Recht über equalseine genaue Art Spiel Überprüfung mitStrings (anderen Klassen lockerer in ihrer mit Typen sein könnten equalsMethoden) .
Olathe
43

Einfach ausgedrückt: String.contentEquals()ist der klügere Bruder von String.equals(), weil es in der Implementierung freier sein kann als String.equals().

Es gibt einige Gründe, warum es eine separate String.contentEquals()Methode gibt. Der wichtigste Grund, den ich denke, ist:

  • Die equalsMethode muss reflexiv sein. Das heißt : x.equals(y) == y.equals(x). Dies impliziert, dass aString.equals(aStringBuffer)dies dasselbe sein müsste wie aStringBuffer.equals(aString). Dies würde erfordern, dass die Java-API-Entwickler eine spezielle Implementierung für Strings in der equals()Methode von StringBuffer, StringBuilder und CharSequence vornehmen. Das wäre ein Chaos.

Dies ist , wo String.contentEqualskommt in. Dies ist eine eigenständige Methode , die sich nicht haben , die strengen Anforderungen und Regeln für Object.equals. Auf diese Weise können Sie den Sinn für "gleichen Inhalt" freier implementieren . Auf diese Weise können Sie beispielsweise intelligente Vergleiche zwischen einem StringBuffer und einem String durchführen.

Und um genau zu sagen, was der Unterschied ist:

  • String.contentEquals()kann den Inhalt von a String, a StringBuilder, a StringBuffer, a CharSequenceund allen abgeleiteten Klassen davon vergleichen. Wenn der Parameter vom Typ String ist, wird String.equals()er ausgeführt.

  • String.equals()vergleicht nur String-Objekte. Alle anderen Objekttypen gelten als ungleich.

  • String.contentEquals()kann vergleichen StringBufferund StringBuilderauf intelligente Weise. Es wird nicht die schwere toString()Methode aufgerufen , die den gesamten Inhalt in ein neues String-Objekt kopiert. Stattdessen wird es mit dem zugrunde liegenden char[]Array verglichen , was großartig ist.

Martijn Courteaux
quelle
31

Diese Antwort wurde bereits von dbw gepostet, aber er hat sie gelöscht, aber er hatte einige sehr gültige Punkte für den Unterschied beim Vergleich der Ausführungszeit, welche Ausnahmen werden ausgelöst,

Wenn Sie sich den Quellcode String # equals und String # contentEquals ansehen , ist klar, dass es zwei überschriebene Methoden für String#contentEqualsdie eine StringBuilderund die andere gibt CharSequence.
Der Unterschied zwischen ihnen,

  1. String#contentEqualswird NPE auslösen, wenn das angegebene Argument lautet, nullaber String#equalszurückgebenfalse
  2. String#equalsvergleicht den Inhalt nur, wenn das angegebene Argument instance of Stringandernfalls zurückgegeben wird. falseIn allen anderen Fällen wird String#contentEqualsder Inhalt aller Objekte zurückgegeben, die die Schnittstelle implementieren CharSequence.
  3. Sie können den Code auch so anpassen, dass String#contentEqualsdas gewünschte falsche Ergebnis zurückgegeben wird, indem Sie die equalsMethode des übergebenen Arguments wie unten gezeigt überschreiben. Sie können diese Änderungen jedoch nicht vornehmen String#equals.
    Der folgende Code wird immertrue so lange erzeugt, wie er 3 Zeichen senthältstring

        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#contentEqualswird langsamer sein als String#Equalsin dem Fall, in dem das angegebene Argument ist instance of Stringund die Länge von beiden gleich Stringist, aber der Inhalt nicht gleich ist.
    Beispiel , wenn die Zeichenfolge sind String s = "madam"und String argPassed = "madan"dann s.contentEquals(argPassed)werden fast doppelt Ausführungszeit in diesem Fall nehmen im Vergleich zus.equals(argPassed)

  5. Wenn die Inhaltslänge für beide Zeichenfolgen nicht gleich ist, hat die Funktion String#contentEqualseine bessere Leistung als String#Equalsin fast allen möglichen Fällen.

Ein weiterer Punkt zu seiner Antwort

  1. String#contentEqualseines StringObjekts wird auch mit dem StringBuilderInhalt verglichen und liefert das entsprechende Ergebnis, während String#Equalses zurückkehrtfalse
Prateek
quelle
4
@dbw diese Antwort ist von der Antwort, die Sie gepostet haben
Prateek
@dbw Außerdem, warum hast du deinen Beitrag überhaupt gelöscht?
MC Emperor
14
  • StringKlassenmethode equals(Object o)führt nur StringVergleiche durch. Aber contentEquals(CharSequence cs)Prüfungen für die Klassen erstreckt sich AbstractStringBuilderalso StringBuffer, StringBuilderund StringKlasse auch (Sie sind alle vom Typ CharSequence).

    String str = "stackoverflow";
    StringBuilder builder = new StringBuilder(str);
    System.out.println(str.equals(builder));
    System.out.println(str.contentEquals(builder));

Ausgabe:

false
true

Der Ausgang des ersten stmt ist , falseweil buildernicht der Typ ist Stringso equals()kehrt falseaber die contentEquals()Kontrollen für den Inhalt aller Art wie StringBuilder, StringBuffer, Stringund wie der Inhalt daher gleich ist true.

  • contentEqualswird werfen, NullPointerExceptionwenn das angegebene Argument ist, nullaber equals()false zurückgeben, da equals () nach instanceOf ( if (anObject instance of String)) prüft, das false zurückgibt, wenn das Argument lautet null.
Ich versuche es
quelle
14

contentEquals(CharSequence cs)::

  • Hiermit können Sie die Gleichheit des angegebenen Zeichenfolgenwerts mit jeder Implementierungsinstanz der Schnittstelle überprüfen java.lang.CharacterSequence (zB CharBuffer, Segment, String, StringBuffer, StringBuilder)

equals(Object anObject)::

  • Hier können Sie Gleichheit gegebenen String - Wert mit jeder Instanz des Typs überprüfen java.lang.String nur

RTFC :)

Da das Lesen der Quelle der beste Weg ist, sie zu verstehen, teile ich die Implementierungen beider Methoden (ab 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;
 }

Es gibt eine andere Methode für String # contentEquals ():

public boolean contentEquals(StringBuffer sb) {
    synchronized(sb) {
        return contentEquals((CharSequence)sb);
    }
}
Amit Sharma
quelle
9

equals()und contentEquals()sind zwei Methoden in der StringKlasse, um zwei stringsund stringmit zu vergleichenStringBuffer .

Die Parameter von contentEquals()sind StringBufferund String(charSequence). equals()wird verwendet, um zwei zu vergleichen, stringsund contentEquals()wird verwendet, um den Inhalt von Stringund zu vergleichenStringBuffer .

Methode contentEqualsund equalssind

public boolean contentEquals(java.lang.StringBuffer);
public boolean contentEquals(java.lang.CharSequence);
public boolean equals(Object o)

Hier ist ein Code, der beide Methoden beschreibt

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);
    }
}

Ausgabe:

 str1.equals(str2) - true
 str1.equals(sb1) - false
 str1.contentEquals(sb1) - true
 str1.contentEquals(sb2) - false
 str1.contentEquals(str2) - true
Asfab
quelle
7

String # equals nimmt Object als Argument und prüft, ob es sich um eine Instanz des String-Objekts handelt oder nicht. Wenn das Argumentobjekt String Object ist, vergleicht es den Inhalt Zeichen für Zeichen. Es gibt true zurück, falls der Inhalt beider Zeichenfolgenobjekte gleich ist.

String # contentEquals die CharSequence-Schnittstelle als Argument. CharSequence kann auf zwei Arten implementiert werden: mithilfe von i) String-Klasse oder (ii) AbstractStringBuilder (übergeordnete Klasse von StringBuffer, StringBuilder)

In contentEquals () wird die Länge vor jeder Objektinstanzprüfung verglichen. Wenn die Länge gleich ist, wird überprüft, ob das Argumentobjekt eine Instanz von AbstractStringBuilder ist oder nicht. Wenn dies der Fall ist (z. B. StringBuffer oder StringBuilder), wird der Inhalt Zeichen für Zeichen überprüft. Wenn das Argument eine Instanz des String-Objekts ist, wird String # gleich von String # contentEquals aufgerufen.

Kurz gesagt,

String # equals vergleicht den Inhalt zeichenweise, falls das Argument auch String-Objekt ist. Und String # contentEquals vergleicht den Inhalt, falls das Argumentobjekt die CharSequence-Schnittstelle implementiert.

String # contentEquals ist langsamer, wenn wir zwei gleich lange String-Inhalte vergleichen, während String # contentEquals intern String # equals für String-Objekte aufruft.

Wenn wir versuchen, Objekte mit unterschiedlicher Inhaltslänge zu vergleichen (sagen wir "abc" mit "abcd"), ist String # contentEquals schneller als String # gleich. Weil die Länge vor jeder Objektinstanzprüfung verglichen wird.

Anirban Pal
quelle
6

Die contentEquals()Methode überprüft , ist der Inhalt derselben zwischen a String, StringBuffer, usw. , die eine Art von char - Sequenz.

fastcodejava
quelle
5

Übrigens ist der historische Grund für den Unterschied, dass String ursprünglich keine Oberklasse hatte, weshalb String.equals () einen String als Argument verwendet. Als CharSequence als Superklasse von String eingeführt wurde, benötigte es einen eigenen Gleichheitstest, der über alle CharSequence-Implementierungen hinweg funktionierte und nicht mit den bereits von String verwendeten equals () kollidierte ... also erhielten wir CharSequence.contentEquals ( ), die von String geerbt wird.

Wenn CharSequence in Java 1.0 vorhanden gewesen wäre, hätten wir wahrscheinlich nur CharSequence.equals () und String würde dies einfach implementieren.

Ah, die Freuden, Sprachen zu entwickeln ...

keshlam
quelle