web-dev-qa-db-fra.com

Comment comparer les chaînes en Java?

J'ai utilisé l'opérateur == dans mon programme pour comparer toutes mes chaînes jusqu'à présent. Cependant, je suis tombé sur un bogue, j'ai changé l'un d'eux en .equals() à la place et cela a corrigé le bogue.

Est-ce que == est mauvais? Quand devrait-il et ne devrait-il pas être utilisé? Quelle est la différence?

726
Nathan H

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

.equals() teste l'égalité des valeurs (si elles sont logiquement "égales").

Objects.equals () vérifie la présence de null avant d'appeler .equals() afin que vous n'ayez pas à le faire (disponible à partir de JDK7, également disponible en Guava ).

String.contentEquals () compare le contenu de la String avec le contenu de toute CharSequence (disponible depuis Java 1.5).

Par conséquent, si vous voulez vérifier si deux chaînes 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

Vous voulez presque toujours utiliser Objects.equals(). Dans le rare situation dans laquelle vous savez vous avez affaire - interné chaînes, vous pouvez utiliser ==.

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

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

Des exemples similaires peuvent également être trouvés dans JLS 3.10.5-1 .

5376
Aaron Maenpaa

== teste les références d'objet, .equals() teste les valeurs de chaîne.

Parfois, il semble que == compare les valeurs, car Java effectue certaines tâches en arrière-plan pour s'assurer que les chaînes en ligne identiques 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 méfiez-vous des nuls!

== gère les chaînes null, 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 nul, dites au lecteur qu’en écrivant

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

Ce qui suit est plus court, mais il est moins évident qu’il vérifie la valeur null (de Java 7):

System.out.print(Objects.equals(fooString1, "bar"));
700
Whatsit

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

.equals() compare les valeurs de chaîne.

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

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

En effet, lorsque vous créez un littéral String, la machine virtuelle Java recherche d'abord ce littéral dans le pool String. Si elle trouve une correspondance, la même référence est attribuée à la nouvelle chaîne. Pour cette raison, nous obtenons:

(a == b=> true) ==

                       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"), la nouvelle instruction String sera créée sur le tas, et cette référence sera donnée à b, de sorte que b recevra une référence sur le tas, et non dans Pool de chaînes.

Maintenant, a pointe vers une chaîne du pool String tandis que b pointe vers une chaîne du 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, il est donc 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, utiliser .equals() est toujours préférable.

427
Ganesh

L'opérateur == vérifie si les deux chaînes sont exactement le même objet.

La méthode .equals() vérifie si les deux chaînes ont la même valeur.

218
Clayton

Les chaînes dans 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 changer la chaîne d'origine. Cela a été fait pour que ces instances de chaîne puissent être mises en cache. Un programme typique contient beaucoup de références de chaîne et la mise en cache de ces instances peut réduire l'encombrement de la mémoire et augmenter les performances du programme.

Lorsque vous utilisez l'opérateur == pour la comparaison de chaînes, vous ne comparez pas le contenu de la chaîne, mais vous comparez en fait l'adresse de mémoire. S'ils sont égaux, il retournera vrai et faux sinon. Alors que equals in string compare le contenu de la chaîne.

La question est donc de savoir si toutes les chaînes sont mises en cache dans le système, comment se fait-il que == renvoie false alors qu'égals renvoie true? C'est possible. Si vous créez une nouvelle chaîne comme String str = new String("Testing"), vous créez 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 pour en faire une partie du cache afin que "MyString" == new String("MyString").intern() renvoie true.

Remarque: L'opérateur == est beaucoup plus rapide que l'égal simplement parce que vous comparez deux adresses de mémoire, mais vous devez vous assurer que le code ne crée pas de nouvelles occurrences String dans le code. Sinon, vous rencontrerez des bugs.

174
Faisal Feroz
String a = new String("foo");
String b = new String("foo");
System.out.println(a == b); // prints false
System.out.println(a.equals(b)); // prints true

Assurez-vous de comprendre pourquoi. C'est parce que la comparaison == compare uniquement les références; la méthode equals() effectue une comparaison caractère par caractère du contenu.

Lorsque vous appelez new pour a et b, chacun obtient une nouvelle référence qui pointe vers le "foo" de la table de chaînes. Les références sont différentes, mais le contenu est le même.

143
duffymo

Oui, c'est mauvais ...

== signifie que vos deux références de chaîne sont exactement le même objet. Vous avez peut-être entendu dire que c'est le cas parce que Java conserve une sorte de table littérale (ce qui est le cas), mais ce n'est pas toujours le cas. Certaines chaînes sont chargées de différentes manières, construites à partir d'autres chaînes, etc., de sorte que vous ne devez jamais supposer que deux chaînes identiques sont stockées au même endroit.

Equals fait la vraie comparaison pour vous.

126
Uri

Oui, == est mauvais pour comparer des chaînes (tous les objets, sauf si vous savez qu'ils sont canoniques). == compare simplement les références d'objet. .equals() teste l'égalité. Pour Strings, ils sont souvent identiques, mais comme vous l'avez découvert, cela n'est pas toujours garanti.

122
cletus

Java possède un pool de chaînes sous lequel Java gère l'allocation de mémoire pour les objets String. Voir Pools de chaînes en Java

Lorsque vous vérifiez (comparez) deux objets à l'aide de l'opérateur ==, il compare l'égalité d'adresse dans le pool de chaînes. Si les deux objets String ont les mêmes références d'adresse, alors il retourne true, sinon false. Mais si vous souhaitez comparer le contenu de deux objets String, vous devez redéfinir la méthode equals.

equals est en fait la méthode de la classe Object, mais elle est remplacée par la classe String et une nouvelle définition est donnée pour comparer le contenu de l'objet.

Example:
    stringObjectOne.equals(stringObjectTwo);

Mais attention, cela respecte le cas de String. Si vous souhaitez une comparaison insensible à la casse, vous devez utiliser la méthode equalsIgnoreCase de la classe String.

Voyons voir:

String one   = "HELLO"; 
String two   = "HELLO"; 
String three = new String("HELLO"); 
String four  = "hello"; 

one == two;   // TRUE
one == three; // FALSE
one == four;  // FALSE

one.equals(two);            // TRUE
one.equals(three);          // TRUE
one.equals(four);           // FALSE
one.equalsIgnoreCase(four); // TRUE
114
Saurabh Agarwal

== compare les références d'objet en Java, et ce n'est pas une exception pour les objets String.

Pour comparer le contenu réel des objets (y compris String), il faut utiliser la méthode equals.

Si une comparaison de deux objets String à l'aide de == s'avère être true, c'est parce que les objets String ont été internés et que Java Virtual La machine ayant plusieurs références pointe vers la même instance de String. Il ne faut pas s’attendre à ce que la comparaison d’un objet String contenant le même contenu qu’un autre objet String utilisant == pour être évaluée comme true.

100
coobird

Je suis d'accord avec la réponse de zacherates.

Mais ce que vous pouvez faire, c'est appeler intern() sur vos chaînes non littérales.

De zacherates exemple:

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

Si vous internez l'égalité de chaîne non littérale est true

new String("test").intern() == "test" ==> true 
100
pgras

.equals() compare les données d'une classe (en supposant que la fonction est implémentée). == compare les emplacements de pointeur (emplacement de l'objet en mémoire).

== renvoie true si les deux objets (ne parlant pas de primitifs) pointent vers l'instance d'objet SAME. .equals() renvoie true si les deux objets contiennent les mêmes données equals() ou == en Java

Cela peut vous aider.

98
Matt Razza

== effectue un contrôle d'égalité référence, afin de déterminer si les 2 objets (les chaînes dans ce cas) se rapportent au même objet dans la mémoire.

La méthode equals() vérifie si les contenus ou les états de 2 objets sont identiques.

Il est évident que == est plus rapide, mais donnera (peut-être) de faux résultats dans de nombreux cas si vous souhaitez simplement indiquer si 2 Strings contient le même texte.

L'utilisation de la méthode equals() est recommandée.

Ne vous inquiétez pas pour la performance. Quelques choses à encourager avec String.equals():

  1. L'implémentation de String.equals() vérifie d'abord l'égalité des références (avec ==), et si les 2 chaînes sont identiques par référence, aucun calcul supplémentaire n'est effectué!
  2. Si les 2 références de chaîne ne sont pas identiques, String.equals() vérifiera ensuite la longueur des chaînes. Cette opération est également rapide car la classe String enregistre la longueur de la chaîne. Il n'est donc pas nécessaire de compter les caractères ni les points de code. Si les longueurs diffèrent, aucune vérification supplémentaire n'est effectuée, nous savons qu'elles ne peuvent pas être égales.
  3. Ce n'est que si nous en sommes là que le contenu des deux chaînes sera réellement comparé. Ce sera une comparaison abrégée: tous les caractères ne seront pas comparés si nous trouvons un caractère incompatible (à la même position dans les 2 chaînes). ), aucun autre caractère ne sera vérifié.

En fin de compte, même si nous avons la garantie que les chaînes sont des internes, l’utilisation de la méthode equals() n’est toujours pas celle de la surcharge que l’on pourrait penser, certainement la méthode recommandée. Si vous souhaitez une vérification efficace des références, utilisez des enum dont la spécification du langage et l’implémentation garantissent que la même valeur enum sera le même objet (par référence).

94
icza

Si vous êtes comme moi, lorsque j'ai commencé à utiliser Java, je souhaitais utiliser l'opérateur "==" pour vérifier si deux instances de String étaient égales, mais pour le meilleur ou pour le pire, ce n'est pas la bonne façon de procéder en Java.

Dans ce tutoriel, je vais vous montrer différentes manières de comparer correctement les chaînes Java, en commençant par l'approche que j'utilise le plus souvent. À la fin de ce tutoriel sur la comparaison de chaînes Java, je vais également expliquer pourquoi l'opérateur "==" ne fonctionne pas lors de la comparaison de chaînes Java.

Option 1: Java Comparaison de chaînes avec la méthode equals La plupart du temps (peut-être 95% du temps), je compare des chaînes avec la méthode equals de la classe Java String, comme celle-ci:

if (string1.equals(string2))

Cette méthode String equals examine les deux chaînes Java. Si elles contiennent exactement la même chaîne de caractères, elles sont considérées comme égales.

En examinant un exemple de comparaison rapide de chaînes avec la méthode equals, si le test suivant était exécuté, les deux chaînes ne seraient pas considérées égales, car les caractères ne sont pas exactement les mêmes (la casse des caractères est différente):

String string1 = "foo";
String string2 = "FOO";

if (string1.equals(string2))
{
    // this line will not print because the
    // Java string equals method returns false:
    System.out.println("The two strings are the same.")
}

Mais, lorsque les deux chaînes contiennent exactement la même chaîne de caractères, la méthode equals renverra true, comme dans cet exemple:

String string1 = "foo";
String string2 = "foo";

// test for equality with the Java string equals method
if (string1.equals(string2))
{
    // this line WILL print
    System.out.println("The two strings are the same.")
}

Option 2: Comparaison de chaînes avec la méthode equalsIgnoreCase

Dans certains tests de comparaison de chaînes, vous voudrez ignorer si les chaînes sont en majuscules ou en minuscules. Lorsque vous souhaitez tester l'égalité de vos chaînes de cette manière, utilisez la méthode equalsIgnoreCase de la classe String, comme suit:

String string1 = "foo";
String string2 = "FOO";

 // Java string compare while ignoring case
 if (string1.equalsIgnoreCase(string2))
 {
     // this line WILL print
     System.out.println("Ignoring case, the two strings are the same.")
 }

Option 3: Java Comparaison de chaînes avec la méthode compareTo

Il existe également un troisième moyen, moins courant, de comparer des chaînes Java, à l’aide de la méthode compareTo de la classe String. Si les deux chaînes sont exactement identiques, la méthode compareTo renverra une valeur de 0 (zéro). Voici un exemple rapide de cette approche de comparaison de chaînes:

String string1 = "foo bar";
String string2 = "foo bar";

// Java string compare example
if (string1.compareTo(string2) == 0)
{
    // this line WILL print
    System.out.println("The two strings are the same.")
}

Pendant que j'écris sur ce concept d'égalité en Java, il est important de noter que le langage Java inclut une méthode equals dans la classe d'objet Java de base. Chaque fois que vous créez vos propres objets et que vous voulez fournir un moyen de voir si deux instances de votre objet sont "égales", vous devez redéfinir (et implémenter) cette méthode equals dans votre classe (de la même manière que le Java language fournit ce comportement d'égalité/comparaison dans la méthode String equals).

Vous voudrez peut-être jeter un oeil à ceci ==, .equals (), compareTo (), et compare ()

82
Mohamed E. ManSour

Une fonction:

public float simpleSimilarity(String u, String v) {
    String[] a = u.split(" ");
    String[] b = v.split(" ");

    long correct = 0;
    int minLen = Math.min(a.length, b.length);

    for (int i = 0; i < minLen; i++) {
        String aa = a[i];
        String bb = b[i];
        int minWordLength = Math.min(aa.length(), bb.length());

        for (int j = 0; j < minWordLength; j++) {
            if (aa.charAt(j) == bb.charAt(j)) {
                correct++;
            }
        }
    }

    return (float) (((double) correct) / Math.max(u.length(), v.length()));
}

Tester:

String a = "This is the first string.";

String b = "this is not 1st string!";

// for exact string comparison, use .equals

boolean exact = a.equals(b);

// For similarity check, there are libraries for this
// Here I'll try a simple example I wrote

float similarity = simple_similarity(a,b);
77
Khaled.K

L'opérateur == vérifie si les deux références pointent sur le même objet ou non. .equals() vérifie le contenu actuel de la chaîne (valeur).

Notez que la méthode .equals() appartient à la classe Object (super classe de toutes les classes). Vous devez le remplacer conformément aux exigences de votre classe, mais pour String, il est déjà implémenté et vérifie si deux chaînes ont la même valeur ou non.

  • Cas 1

    String s1 = "Stack Overflow";
    String s2 = "Stack Overflow";
    s1 == s2;      //true
    s1.equals(s2); //true
    

    Raison: les littéraux de chaîne créés sans null sont stockés dans le pool Chaîne dans la zone permgen du tas. Ainsi, s1 et s2 désignent tous les deux le même objet du pool.

  • Cas 2

    String s1 = new String("Stack Overflow");
    String s2 = new String("Stack Overflow");
    s1 == s2;      //false
    s1.equals(s2); //true
    

    Raison: si vous créez un objet String à l'aide du mot clé new, un espace distinct lui est alloué sur le tas.

75
Aniket Thakur

== compare la valeur de référence des objets alors que la méthode equals() présente dans la classe Java.lang.String compare le contenu de l'objet String (à un autre objet).

53
samkit shah

Je pense que lorsque vous définissez une String, vous définissez un objet. Vous devez donc utiliser .equals(). Lorsque vous utilisez des types de données primitifs, vous utilisez ==, mais avec String (et tout objet), vous devez utiliser .equals().

50
fabricioflores

Si la méthode equals() est présente dans la classe Java.lang.Object, il est alors prévu de vérifier l'équivalence de l'état des objets! Cela signifie que le contenu des objets. Alors que l'opérateur == doit vérifier si les instances d'objet réelles sont identiques ou non.

Exemple

Considérons deux variables de référence différentes, str1 et str2:

str1 = new String("abc");
str2 = new String("abc");

Si vous utilisez la equals()

System.out.println((str1.equals(str2))?"TRUE":"FALSE");

Vous obtiendrez le résultat sous la forme TRUE si vous utilisez ==.

System.out.println((str1==str2) ? "TRUE" : "FALSE");

Vous obtiendrez maintenant le FALSE en sortie, car str1 et str2 désignent deux objets différents, même s'ils partagent le même contenu de chaîne. C'est à cause de new String() qu'un nouvel objet est créé à chaque fois.

48
Rakesh KR

L'opérateur == est toujours destiné à comparaison de référence d'objet, alors que la classe String . La méthode equals () est remplacée par comparaison de conten:

String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1 == s2); // It prints false (reference comparison)
System.out.println(s1.equals(s2)); // It prints true (content comparison)
43
sham.y

Vous pouvez également utiliser la méthode compareTo() pour comparer deux chaînes. Si le résultat compareTo est 0, les deux chaînes sont égales, sinon les chaînes comparées ne sont pas égales.

Le == compare les références et ne compare pas les chaînes réelles. Si vous avez créé chaque chaîne à l'aide de new String(somestring).intern(), vous pouvez utiliser l'opérateur == pour comparer deux chaînes, sinon les méthodes equals () ou compareTo ne peuvent être utilisées.

Il est garanti que tous les objets ont une méthode .equals() puisque Object contient une méthode, .equals(), qui renvoie un booléen. C'est le travail de la sous-classe de remplacer cette méthode si une définition supplémentaire est requise. Sans lui (c'est-à-dire en utilisant ==), seules les adresses de mémoire sont vérifiées entre deux objets afin de vérifier leur égalité. String remplace cette méthode .equals() et, au lieu d'utiliser l'adresse mémoire, renvoie la comparaison des chaînes au niveau du caractère pour assurer leur égalité.

Une remarque clé est que les chaînes sont stockées dans un pool global afin qu’une fois créées, les chaînes sont définitivement stockées dans un programme à la même adresse. Les chaînes ne changent pas, elles sont immuables. C’est pourquoi il est déconseillé d’utiliser une concaténation de chaînes normale si vous avez un nombre considérable de traitements à effectuer. À la place, vous utiliseriez les classes StringBuilder fournies. Rappelez-vous que les pointeurs vers cette chaîne peuvent changer et si vous vouliez savoir si deux pointeurs étaient identiques == serait un bon moyen d’aller. Les cordes elles-mêmes ne le sont pas.

39
James

En Java, lorsque l'opérateur “==” est utilisé pour comparer 2 objets, il vérifie si les objets se réfèrent au même emplacement en mémoire. En d'autres termes, il vérifie si les 2 noms d'objet sont des références au même emplacement mémoire.

La classe Java String remplace en réalité l'implémentation par défaut de equals () dans la classe Object. Elle redéfinit la méthode afin qu'elle ne vérifie que les valeurs des chaînes, et non leurs emplacements en mémoire. Cela signifie que si vous appelez la méthode equals () pour comparer 2 objets String, tant que la séquence de caractères est identique, les deux objets sont considérés comme égaux.

L'opérateur == vérifie si les deux chaînes sont exactement le même objet.

La méthode .equals() vérifie si les deux chaînes ont la même valeur.

35
Lijo