Différence entre les méthodes String # equals et String # contentEquals


Réponses:


171

Le String#equals()non seulement compare le contenu de la chaîne, mais aussi vérifie si l'autre objet est une instance d'un String. Le String#contentEquals()seul compare le contenu (la séquence de caractères) et ne vérifie pas si l'autre objet est également une instance de String. Il peut être tout aussi longtemps qu'il est une mise en œuvre CharSequencequi couvre ao String, StringBuilder, StringBuffer, CharBuffer, etc.


12
Alors, est-ce comme les opérateurs ==(contentEquals) et ===(equals) en javascript?
anestv

2
@anestv En Java, l' ==opérateur vous permettra uniquement de comparer les références et non le contenu de deux objets.
Stephan

2
@Alex pour clarifier, l'opérateur == en Java sert à vérifier si deux objets pointent vers le même emplacement en mémoire, ou si deux types primitifs (byte, short, int, long, float, double, char, boolean) sont égaux.
La-comadreja

2
@Stephan, le ==mentionné n'est que JavaScript; il n'est jamais mentionné concernant Java.
Olathe

@anestv, il y a des différences ( ==en JavaScript, c'est beaucoup plus lâche que contentEquals, ce qui ne touchera pas aux nombres, par exemple), mais vous avez raison de equalsvérifier une correspondance de type exacte avecStrings (d'autres classes peuvent être plus lâches avec des types dans leurs equalsméthodes) .
Olathe

43

Pour le dire facilement: String.contentEquals()est le frère le plus intelligent de String.equals(), car il peut être plus libre dans la mise en œuvre que String.equals().

Il existe certaines raisons pour lesquelles il existe une String.contentEquals()méthode distincte . La raison la plus importante à mon avis est:

  • La equalsméthode doit être réflexive. Cela signifie que: x.equals(y) == y.equals(x). Cela implique que cela aString.equals(aStringBuffer)devrait être le même que aStringBuffer.equals(aString). Cela nécessiterait que les développeurs d'API Java réalisent également une implémentation spéciale pour Strings dans la equals()méthode StringBuffer, StringBuilder et CharSequence. Ce serait un gâchis.

C'est là String.contentEqualsqu'intervient. Il s'agit d'une méthode autonome qui n'a pas à suivre les exigences et les règles strictes pour Object.equals. De cette façon, vous pouvez mettre en œuvre le sens de «contenu égal» plus librement. Cela vous permet de faire des comparaisons intelligentes entre un StringBuffer et un String, par exemple.

Et pour dire quelle est exactement la différence:

  • String.contentEquals()peut comparer le contenu de a String, a StringBuilder, a StringBuffer, a CharSequenceet toutes les classes dérivées de ceux-ci. Si le paramètre est de type String, alors String.equals()soyez exécuté.

  • String.equals()compare uniquement les objets String. Tous les autres types d'objets sont considérés comme différents.

  • String.contentEquals()peut comparer StringBufferet StringBuilderde manière intelligente. Il n'appelle pas la toString()méthode lourde , qui copie tout le contenu dans un nouvel objet String. Au lieu de cela, il se compare au char[]tableau sous-jacent , ce qui est excellent.


31

Cette réponse était déjà postée par dbw mais il l'a supprimée mais il avait des points très valables pour la différence en comparant le temps d'exécution, les exceptions levées,

Si vous regardez le code source String # equals et String # contentEquals, il est clair qu'il existe deux méthodes remplacées pour l' String#contentEqualsune qui prennent StringBuilderet l'autre CharSequence.
La différence entre eux,

  1. String#contentEqualslancera NPE si l'argument fourni est nullmais String#equalsretournerafalse
  2. String#equalscompare le contenu uniquement lorsque l'argument fourni est instance of Stringsinon il retournera falsedans tous les autres cas mais par contre String#contentEqualsvérifie le contenu de tous les objets qui implémentent l'interface CharSequence.
  3. Vous pouvez également modifier le code pour String#contentEqualsrenvoyer le mauvais résultat ou le résultat souhaité en remplaçant la equalsméthode de l'argument transmis comme indiqué ci-dessous, mais vous ne pouvez pas effectuer ces modifications avec String#equals.
    Le code ci-dessous produira toujourstrue tant qu'il scontient tout stringce qui est long de 3 caractères

        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#contentEqualssera plus lent que String#Equalsdans le cas où l'argument fourni est instance of Stringet la longueur des deux Stringest la même mais le contenu n'est pas égal.
    Exemple si la chaîne est String s = "madam"et prendra String argPassed = "madan"alors s.contentEquals(argPassed)presque le double du temps d'exécution dans ce cas par rapport às.equals(argPassed)

  5. Si la longueur du contenu n'est pas la même pour les deux chaînes, la fonction String#contentEqualsaura de meilleures performances que String#Equalsdans presque tous les cas possibles.

Encore un point à ajouter à sa réponse

  1. String#contentEqualsd'un Stringobjet sera également comparé au StringBuildercontenu et fournira le résultat approprié tandis que String#Equalsretournerafalse

4
@dbw cette réponse est tirée de la réponse que vous avez publiée
Prateek

@dbw D'ailleurs, pourquoi avez-vous supprimé votre message de toute façon?
MC Emperor

14
  • StringLa equals(Object o)méthode de classe ne fait que la Stringcomparaison. Mais contentEquals(CharSequence cs)vérifie les classes étend, AbstractStringBuilderc'est -à- dire StringBuffer, StringBuilderet Stringclasse aussi (ils sont tous de type CharSequence).

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

production:

false
true

La sortie de la première stmt est falseparce builderest pas de type Stringsi les equals()rendements , falsemais les contentEquals()contrôles pour le contenu de tout type comme StringBuilder, StringBuffer, Stringet que le contenu est donc même true.

  • contentEqualslancera NullPointerExceptionsi l'argument fourni est nullmais equals()retournera false car equals () vérifie instanceOf ( if (anObject instance of String)) qui retourne false si l'argument est null.

14

contentEquals(CharSequence cs):

  • Vous permet de vérifier l' égalité de la valeur chaîne donnée avec une instance de mise en œuvre de l' interface java.lang.CharacterSequence(par exemple CharBuffer, Segment, String, StringBuffer, StringBuilder)

equals(Object anObject):

  • Vous permet de vérifier l'égalité de la valeur de chaîne donnée avec n'importe quelle instance de type java.lang.String uniquement

RTFC :)

Puisque la lecture de la source est la meilleure façon de la comprendre, je partage les implémentations des deux méthodes (à partir de 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;
 }

Il existe une autre méthode de String # contentEquals ():

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

9

equals()et il contentEquals()existe deux méthodes en Stringclasse pour comparer deux stringset stringavec StringBuffer.

Les paramètres de contentEquals()sont StringBufferet String(charSequence). equals()est utilisé pour comparer deux stringset contentEquals()est utilisé pour comparer le contenu de Stringet StringBuffer.

Méthode contentEqualset equalssont

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

Voici un code qui décrit les deux méthodes

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

Production:

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

7

String # equals prend Object comme argument et vérifie qu'il s'agit d'une instance de l'objet String ou non. Si l'objet argument est String Object, il compare le contenu caractère par caractère. Elle renvoie true si le contenu des deux objets chaîne est le même.

String # contentEquals prend l'interface CharSequence comme argument. CharSequence peut être implémenté de 2 façons - en utilisant i) la classe String ou (ii) AbstractStringBuilder (classe parent de StringBuffer, StringBuilder)

Dans contentEquals (), la longueur est comparée avant toute vérification d'instance d'objet. Si la longueur est la même, alors il vérifie que l'argument est une instance de AbstractStringBuilder ou non. Si tel est le cas (c'est-à-dire StringBuffer ou StringBuilder), le contenu est vérifié caractère par caractère. Si l'argument est une instance de l'objet String, String # est égal à appelé à partir de String # contentEquals.

Donc en bref,

String # equals compare le contenu caractère par caractère si l'argument case est également un objet String. Et String # contentEquals compare le contenu dans le cas où l'objet argument implémente l'interface CharSequence.

String # contentEquals est plus lent si nous comparons deux contenus de chaîne de même longueur que String # contentEquals appelle en interne String # equals pour l'objet String.

Dans le cas où nous essayons de comparer des objets avec une longueur de contenu différente (disons "abc" avec "abcd"), alors String # contentEquals est plus rapide que String # equals. Parce que la longueur est comparée avant toute vérification d'instance d'objet.


6

Les contentEquals()contrôles de procédé est le contenu sont identiques entre String, StringBufferetc qui une sorte de séquence de carbonisation.


5

BTW, la raison historique de la différence est que String n'avait pas à l'origine de superclasse, donc String.equals () prend une String comme argument. Lorsque CharSequence a été introduit comme la superclasse de String, il lui fallait un test d'égalité qui fonctionnait sur toutes les implémentations de CharSequence, et qui n'entrerait pas en conflit avec equals () déjà utilisé par String ... donc nous avons obtenu CharSequence.contentEquals ( ), hérité de String.

Si CharSequence était présent dans Java 1.0, nous n'aurions probablement que CharSequence.equals () et String implémenterait simplement cela.

Ah, les joies de l'évolution des langues ...

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.