Differenza tra i metodi String # equals e String # contentEquals


Risposte:


171

Il String#equals()non solo confronta il contenuto della stringa, ma controlla anche se l'altro oggetto è anche un'istanza di a String. L' String#contentEquals()unico confronta i contenuti (la sequenza di caratteri) e non controlla se l'altro oggetto è anche un'istanza di String. Può essere qualsiasi cosa, purché si tratta di un'implementazione di CharSequenceche copre AO String, StringBuilder, StringBuffer, CharBuffer, etc.


12
Quindi, è come gli operatori ==(contentEquals) e ===(uguale a) in javascript?
Anestv,

2
@anestv In Java, l' ==operatore ti consentirà solo di confrontare i riferimenti e non il contenuto di due oggetti.
Stephan,

2
@Alex per chiarire, l'operatore == in Java serve per verificare se due oggetti puntano nella stessa posizione in memoria o se due tipi primitivi (byte, short, int, long, float, double, char, boolean) sono uguali.
La-comadreja,

2
@Stephan, il ==citato è solo JavaScript; non è mai stato menzionato per quanto riguarda Java.
Olathe,

@anestv, ci sono differenze ( ==in JavaScript è molto più sciolto di contentEquals, che non toccherà i numeri, per esempio), ma hai ragione nel equalsverificare la corrispondenza esatta del tipo conStrings (altre classi potrebbero essere più libere con i tipi nei loro equalsmetodi) .
Olathe,

43

Per dirla facilmente: String.contentEquals()è il fratello più intelligente di String.equals(), perché può essere più libero nell'implementazione che String.equals().

Ci sono alcuni motivi per cui esiste un String.contentEquals()metodo separato . Il motivo più importante che penso è:

  • Il equalsmetodo deve essere riflessivo. Ciò significa che: x.equals(y) == y.equals(x). Ciò implica che aString.equals(aStringBuffer)dovrebbe essere lo stesso di aStringBuffer.equals(aString). Ciò richiederebbe agli sviluppatori dell'API Java di realizzare un'implementazione speciale per Strings anche nel equals()metodo StringBuffer, StringBuilder e CharSequence. Questo sarebbe un casino.

Qui è dove String.contentEqualsentra in gioco. Questo è un metodo di stand-alone che non non deve seguire i severi requisiti e le regole per Object.equals. In questo modo, puoi implementare il senso di "uguale contenuto" più liberamente. Ciò consente, ad esempio, di effettuare confronti intelligenti tra StringBuffer e String.

E dire qual è esattamente la differenza:

  • String.contentEquals()può confrontare i contenuti di a String, a StringBuilder, a StringBuffer, a CharSequencee tutte le classi derivate di questi. Se il parametro è di tipo String, allora String.equals()esegui.

  • String.equals()confronta solo oggetti String. Tutti gli altri tipi di oggetti sono considerati non uguali.

  • String.contentEquals()può confrontare StringBuffere StringBuilderin modo intelligente. Essa non chiamare il pesante toString()metodo, che copia l'intero contenuto di un nuovo oggetto String. Invece, si confronta con l' char[]array sottostante , il che è fantastico.


31

Questa risposta è stata già pubblicata da dbw ma l'ha eliminata ma aveva alcuni punti molto validi per la differenza durante il confronto dei tempi di esecuzione, quali eccezioni vengono generate,

Se guardi il codice sorgente String # equals e String # contentEquals è chiaro che ci sono due metodi sovrascritti per String#contentEqualsuno che accetta StringBuildere l'altro CharSequence.
La differenza tra loro,

  1. String#contentEqualsgenererà NPE se l'argomento fornito è nullma String#equalsrestituiràfalse
  2. String#equalsconfronta il contenuto solo quando l'argomento fornito è instance of Stringaltrimenti tornerà falsein tutti gli altri casi ma d'altra parte String#contentEqualscontrolla il contenuto di tutti gli oggetti che implementano l'interfaccia CharSequence.
  3. Puoi anche modificare il codice in modo che String#contentEqualsrestituisca il risultato o il risultato errato che desideri sostituendo il equalsmetodo dell'argomento passato come mostrato di seguito, ma non puoi fare quelle modifiche String#equals.
    Il codice seguente produrrà sempretrue finché scontiene string3 caratteri

        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#contentEqualssarà più lento quindi String#Equalsnel caso in cui l'argomento fornito sia instance of Stringe la lunghezza di entrambi Stringsia la stessa ma i contenuti non siano uguali.
    Esempio se la stringa è String s = "madam"e String argPassed = "madan"quindi s.contentEquals(argPassed)impiegherà quasi il doppio del tempo di esecuzione in questo caso rispetto as.equals(argPassed)

  5. Se la lunghezza del contenuto non è la stessa per entrambe le stringhe, la funzione String#contentEqualsavrà prestazioni migliori rispetto String#Equalsa quasi tutti i casi possibili.

Un altro punto da aggiungere alla sua risposta

  1. String#contentEqualsdi un Stringoggetto verrà inoltre confrontato con il StringBuildercontenuto e fornirà il risultato appropriato mentre String#Equalsverrà restituitofalse

4
@dbw questa risposta proviene dalla risposta che hai pubblicato
Prateek il

@dbw Inoltre, perché hai cancellato comunque il tuo post?
MC Emperor

14
  • Stringil equals(Object o)metodo class fa solo un Stringconfronto. Ma i contentEquals(CharSequence cs)controlli per le classi si estendono AbstractStringBuildercioè StringBuffer, StringBuildere Stringanche la classe (sono tutti di tipo CharSequence).

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

produzione:

false
true

L'uscita del primo stmt è falseperché buildernon è di tipo Stringcosì equals()rendimenti falsema i contentEquals()controlli per il contenuto di tutti del tipo come StringBuilder, StringBuffer, Stringe il contenuto è lo stesso di conseguenza true.

  • contentEqualsverrà generato NullPointerExceptionse l'argomento fornito è nullma equals()restituirà false perché equals () controlla ad esempioOf ( if (anObject instance of String)) che restituisce false se l'argomento è null.

14

contentEquals(CharSequence cs):

  • Consente di controllare l'uguaglianza di dato valore stringa con qualsiasi istanza implementazione dell'interfaccia java.lang.CharacterSequence(ad esempio, CharBuffer, Segment, String, StringBuffer, StringBuilder)

equals(Object anObject):

  • Consente di controllare l'uguaglianza di dato valore stringa con qualsiasi istanza di tipo java.lang.String solo

RTFC :)

Poiché la lettura della fonte è il modo migliore per capirla, condivido le implementazioni di entrambi i metodi (a partire da 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;
 }

Esiste un altro metodo di String # contentEquals ():

public boolean contentEquals(StringBuffer sb) {
    synchronized(sb) {
        return contentEquals((CharSequence)sb);
    }
}

9

equals()e contentEquals()sono due metodi in Stringclasse per confrontare due stringse stringcon StringBuffer.

I parametri di contentEquals()are StringBuffere String(charSequence). equals()viene utilizzato per confrontare due stringse contentEquals()viene utilizzato per confrontare i contenuti di Stringe StringBuffer.

Metodo contentEqualse lo equalssono

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

Ecco un codice che descrive entrambi i metodi

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

Produzione:

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

7

String # equals accetta Object come argomento e verifica che sia un'istanza di String object o meno. Se l'oggetto argomento è String Object, confronta il contenuto carattere per carattere. Restituisce vero nel caso in cui il contenuto di entrambi gli oggetti stringa sia uguale.

String # contentEquals utilizza l'interfaccia CharSequence come argomento. CharSequence può essere implementato in 2 modi: utilizzando i) Classe String o (ii) AbstractStringBuilder (classe padre di StringBuffer, StringBuilder)

In contentEquals () la lunghezza viene confrontata prima di qualsiasi controllo dell'istanza dell'oggetto. Se la lunghezza è la stessa, controlla che l'oggetto dell'argomento sia un'istanza di AbstractStringBuilder o meno. Se è così (cioè StringBuffer o StringBuilder), il contenuto viene controllato carattere per carattere. Nel caso in cui l'argomento sia un'istanza dell'oggetto String, allora String # equivale a String # contentEquals.

Quindi in breve,

String # equivale a confrontare il carattere carattere per carattere nel caso in cui l'argomento sia anche oggetto String. E String # contentEquals confronta il contenuto nell'oggetto caso argomento implementa l'interfaccia CharSequence.

String # contentEquals è più lento nel caso in cui confrontiamo due contenuti di stringa della stessa lunghezza di String # contentEquals chiama internamente String # uguale per oggetto String.

Nel caso in cui proviamo a confrontare oggetti con lunghezza del contenuto differente (ad esempio "abc" con "abcd"), allora String # contentEquals è più veloce di String # uguale. Perché la lunghezza viene confrontata prima di qualsiasi controllo dell'istanza dell'oggetto.


6

I contentEquals()controlli metodo è il contenuto sono uguali tra String, StringBuffer, ecc che qualche tipo di sequenza char.


5

A proposito, la ragione storica della differenza è che String inizialmente non aveva una superclasse, quindi String.equals () prende una stringa come argomento. Quando CharSequence è stato introdotto come superclasse di String, aveva bisogno di un test di uguaglianza a sé stante che funzionasse su tutte le implementazioni di CharSequence e che non si scontrasse con l'equals () già utilizzato da String ... quindi abbiamo ottenuto CharSequence.contentEquals ( ), ereditato da String.

Se CharSequence fosse presente in Java 1.0, avremmo solo CharSequence.equals () e String lo implementerebbe semplicemente.

Ah, le gioie delle lingue in evoluzione ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.