723 votes

Comment comparer des chaînes de caractères en Java ?

J'ai utilisé le == dans mon programme pour comparer toutes mes chaînes de caractères jusqu'à présent. Cependant, j'ai rencontré un bug, j'ai changé l'une d'entre elles en .equals() à la place, et cela a corrigé le bug.

Est == mauvais ? Quand faut-il l'utiliser et quand ne faut-il pas l'utiliser ? Quelle est la différence ?

12 votes

Il est également bon de savoir que, si vous remplacez la méthode .equals (), assurez-vous de remplacer la méthode .hashcode (), sinon vous finirez par violer la relation d'équivalence entre equals et hashcode. Pour plus d'informations, consultez la documentation java.

0 votes

Je laisse un lien vers mon explication du pourquoi == fonctionne comme sur les Objets : stackoverflow.com/a/19966154/2284641

0 votes

== fonctionnera parfois, car java dispose d'un pool de chaînes de caractères, dans lequel il tente de réutiliser les références mémoire des chaînes de caractères les plus utilisées. Mais == compare que les objets sont égaux, pas les valeurs... donc .equals() est le bon usage que vous voulez utiliser.

6046voto

Aaron Maenpaa Points 39173

== teste l'égalité des références (s'il s'agit du même objet).

.equals() des tests d'égalité des valeurs (si elles sont logiquement "égales").

Objets.equals() contrôles pour null avant d'appeler .equals() pour que vous n'ayez pas à le faire (disponible à partir de JDK7, également disponible en Goyave ).

Par conséquent, si vous voulez tester si deux chaînes de caractères ont la même valeur, vous voudrez probablement utiliser Objects.equals() .

// These two have the same value
new String("test").equals("test") // --> true 

// ... but they are not the same object
new String("test") == "test" // --> false 

// ... neither are these
new String("test") == new String("test") // --> false 

// ... but these are because literals are interned by 
// the compiler and thus refer to the same object
"test" == "test" // --> true 

// ... string literals are concatenated by the compiler
// and the results are interned.
"test" == "te" + "st" // --> true

// ... but you should really just call Objects.equals()
Objects.equals("test", new String("test")) // --> true
Objects.equals(null, "test") // --> false
Objects.equals(null, null) // --> true

Tu as presque toujours veulent utiliser Objects.equals() . Dans le rare situation où vous connaître vous avez affaire à interné les cordes, vous peut utiliser == .

De JLS 3.10.5. Littéraux de chaîne :

De plus, un littéral de chaîne de caractères fait toujours référence à l'élément même instance de la classe String . En effet, les chaînes littérales - ou, plus généralement, les chaînes de caractères qui sont les valeurs d'expressions constantes ( §15.28 ) - sont "internés" de manière à partager des instances uniques, en utilisant la méthode String.intern .

On trouve également des exemples similaires dans JLS 3.10.5-1 .

Autres méthodes à envisager

String.equalsIgnoreCase() l'égalité des valeurs qui ignore la casse. Attention, cependant, cette méthode peut avoir des résultats inattendus dans divers cas liés à la localisation, cf. cette question .

String.contentEquals() compare le contenu de la String avec le contenu de tout CharSequence (disponible depuis Java 1.5). Elle vous évite de devoir transformer votre StringBuffer, etc. en String avant d'effectuer la comparaison d'égalité, mais vous laisse le soin de vérifier les nullités.

6 votes

Si == vérifie l'égalité des références, pourquoi n==5 a-t-il un sens ? 5 n'est pas une variable

13 votes

@HritRoy Parce que == vérifie le valeur d'une variable. Lorsque vous avez un objet, la variable qui fait référence à l'objet a pour référence l'objet en tant que valeur . Ainsi, vous comparez les références lors de la comparaison de deux variables avec == . Lors de la comparaison d'un type de données primitif tel que int il s'agit toujours du même cas. Une variable de type int a pour valeur le nombre entier. Ainsi, vous comparez les valeurs de deux int s en utilisant == . Si le int est la valeur d'une variable ou un nombre magique n'a pas d'importance. En outre : A référence n'est rien d'autre qu'un nombre qui fait référence à la mémoire.

0 votes

J'ajouterais que même si vous savez que vos cordes sont internées, vous devrait utiliser equals parce que c'est plus évidemment correct. Ou bien, vous devriez utiliser un enum au lieu de chaînes de caractères.

782voto

Whatsit Points 3292

== teste les références d'objets, .equals() teste les valeurs des chaînes de caractères.

Parfois, on a l'impression que == compare les valeurs, car Java effectue des opérations en coulisse pour s'assurer que des chaînes de caractères identiques en ligne sont bien le même objet.

Par exemple :

String fooString1 = new String("foo");
String fooString2 = new String("foo");

// Evaluates to false
fooString1 == fooString2;

// Evaluates to true
fooString1.equals(fooString2);

// Evaluates to true, because Java uses the same object
"bar" == "bar";

Mais attention aux nuls !

== poignées null les cordes sont bien, mais appeler .equals() à partir d'une chaîne nulle provoquera une exception :

String nullString1 = null;
String nullString2 = null;

// Evaluates to true
System.out.print(nullString1 == nullString2);

// Throws a NullPointerException
System.out.print(nullString1.equals(nullString2));

Donc si vous savez que fooString1 peut être nulle, dites au lecteur qu'en écrivant

System.out.print(fooString1 != null && fooString1.equals("bar"));

Les suivantes sont plus courtes, mais il est moins évident qu'elles vérifient la présence de null :

System.out.print("bar".equals(fooString1));  // "bar" is never null
System.out.print(Objects.equals(fooString1, "bar"));  // Java 7 required

94 votes

Parfois, on a l'impression que "==" compare des valeurs, -- == faire comparez toujours les valeurs ! (C'est juste que certaines valeurs sont des références !)

8 votes

Hélas, il n'existe pas de méthode statique pour isNullOrEmpty(), ni de surcharge personnalisée des opérateurs, ce qui rend cette partie de Java plus compliquée qu'en C# ou Python. Et comme Java n'a pas de méthodes d'extension, vous ne pouvez pas écrire votre propre utilitaire pour étendre java.lang.String. N'est-ce pas ? Que pensez-vous de sous-classer String, d'ajouter cette méthode utilitaire statique et de toujours utiliser MyString à la place ? Une méthode statique avec deux paramètres pour effectuer des comparaisons à sécurité nulle serait également intéressante dans cette sous-classe.

8 votes

Groovy rend cette tâche un peu plus facile avec la fonction opérateur de navigation sûr ( groovy.codehaus.org/ ), ?. . Cela convertirait nullString1?.equals(nullString2); en une déclaration entièrement nulle. Cependant, cela ne sert à rien si vous avez validString?.equals(nullString); -- qui lève toujours une exception.

479voto

Ganesh Points 793

== compare les références d'objets.

.equals() compare des valeurs de type String.

Parfois == donne l'illusion de comparer les valeurs des chaînes, comme dans les cas suivants :

String a="Test";
String b="Test";
if(a==b) ===> true

En effet, lorsque vous créez un littéral de chaîne, la JVM recherche d'abord ce littéral dans le pool de chaînes, et si elle trouve une correspondance, cette même référence sera donnée à la nouvelle chaîne. De ce fait, nous obtenons :

(a==b) ===> vrai

                       String Pool
     b -----------------> "test" <-----------------a

Cependant, == échoue dans le cas suivant :

String a="test";
String b=new String("test");
if (a==b) ===> false

Dans ce cas, pour new String("test") l'instruction new String sera créée sur le tas, et cette référence sera donnée à b donc b se verra attribuer une référence sur le tas, et non dans le pool String.

Maintenant a pointe vers une chaîne dans le pool de chaînes alors que b pointe vers une chaîne sur le tas. A cause de cela, nous obtenons :

si(a==b) ===> faux.

                String Pool
     "test" <-------------------- a

                   Heap
     "test" <-------------------- b

Alors que .equals() compare toujours une valeur de String, donc il donne vrai dans les deux cas :

String a="Test";
String b="Test";
if(a.equals(b)) ===> true

String a="test";
String b=new String("test");
if(a.equals(b)) ===> true

Donc, en utilisant .equals() est toujours mieux.

3 votes

.equals() compare les deux instances, quelle que soit la manière dont equals est implémenté pour les comparer. Cela peut être ou non la comparaison de la sortie de toString.

3 votes

@Jacob Classe d'objets .equals() compare les instances (références/adresses) alors que la classe String .equals() est surchargée pour comparer le contenu (chars).

2 votes

Il est bon de souligner les différences entre le pool de chaînes et le tas de Java, car elles sont certainement importantes. pas la même chose. Dans le pool de chaînes, Java essaie de "cacher" String pour économiser l'empreinte mémoire comme String est connu pour être immuable (j'espère, je le dis correctement ici). Vérifiez également stackoverflow.com/questions/3052442/

234voto

Clayton Points 2481

Le site == L'opérateur vérifie si les deux chaînes de caractères sont exactement le même objet.

Le site .equals() vérifiera si les deux chaînes de caractères ont la même valeur.

5 votes

En général, je recommande fortement la bibliothèque Apache Commons : [commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/](https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringUtils.html#equals(java.lang.String) , java.lang.String)

188voto

Faisal Feroz Points 4926

Les chaînes de caractères en Java sont immuables. Cela signifie que chaque fois que vous essayez de changer/modifier la chaîne, vous obtenez une nouvelle instance. Vous ne pouvez pas modifier la chaîne originale. Cela a été fait pour que ces instances de chaînes puissent être mises en cache. Un programme typique contient beaucoup de références de chaînes de caractères et la mise en cache de ces instances peut réduire l'empreinte mémoire et augmenter les performances du programme.

Lorsque vous utilisez l'opérateur == pour comparer des chaînes de caractères, vous ne comparez pas le contenu de la chaîne, mais vous comparez en fait l'adresse mémoire. S'ils sont tous deux égaux, l'opérateur renvoie true (vrai), sinon false (faux). Alors que equals dans une chaîne de caractères compare le contenu de la chaîne.

Donc la question est que si toutes les chaînes sont mises en cache dans le système, comment se fait-il que == renvoie faux alors que equals renvoie vrai ? Eh bien, c'est possible. Si vous créez une nouvelle chaîne de caractères comme String str = new String("Testing") vous finissez par créer une nouvelle chaîne dans le cache, même si le cache contient déjà une chaîne ayant le même contenu. En bref "MyString" == new String("MyString") retournera toujours false.

Java parle également de la fonction intern() qui peut être utilisée sur une chaîne de caractères pour l'intégrer dans le cache. "MyString" == new String("MyString").intern() retournera vrai.

Remarque : l'opérateur == est beaucoup plus rapide que equals simplement parce que vous comparez deux adresses mémoire, mais vous devez être sûr que le code ne crée pas de nouvelles instances de String dans le code. Sinon, vous rencontrerez des bogues.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X