Comment comparer des chaînes en Java
Comparez des chaînes Java avec equals, equalsIgnoreCase, compareTo et évitez les pièges courants liés à ==.
Comparer deux valeurs String en Java est l'une des premières erreurs que commet un débutant, car l'opérateur == compare silencieusement des références plutôt que des contenus. Ce chapitre présente les façons correctes et idiomatiques de tester l'égalité et l'ordre des chaînes — equals, equalsIgnoreCase, compareTo, et le Objects.equals sécurisé contre les valeurs null — et explique précisément quand chacun est le bon outil.
Pour comprendre pourquoi des littéraux identiques peuvent être ==, consultez le pool de chaînes ; pour une vue d'ensemble plus large des techniques de comparaison, consultez la comparaison de chaînes Java.
Égalité de contenu avec equals
Pour vérifier si deux chaînes contiennent les mêmes caractères, appelez equals :
String a = "hello";
String b = new String("hello");
boolean same = a.equals(b); // true — same charactersequals parcourt les deux séquences de caractères et renvoie true uniquement lorsqu'elles ont la même longueur et les mêmes caractères dans le même ordre. C'est la méthode que vous voulez utiliser 99 % du temps lorsque vous demandez « ces deux chaînes contiennent-elles le même texte ? ».
Une astuce défensive courante consiste à appeler equals sur un littéral de chaîne afin que le récepteur ne soit jamais null :
if ("yes".equals(userInput)) { ... } // safe even if userInput is nullPourquoi == est le piège classique
== n'examine pas du tout les caractères — il demande « ces deux éléments sont-ils exactement le même objet en mémoire ? ». Parce que le compilateur interne les littéraux de chaîne (stocke une seule copie partagée dans un pool), deux littéraux identiques peuvent se trouver être ==, ce qui amène les gens à croire que == compare du texte. Ce n'est pas le cas : dès qu'une chaîne provient de new, d'une saisie utilisateur ou d'une concaténation au moment de l'exécution, == renvoie false même pour un texte identique.
| Expression | Résultat | Pourquoi |
|---|---|---|
"java" == "java" | true | Les deux font référence au même littéral interné |
"java" == new String("java") | false | new crée un objet distinct |
"java".equals(new String("java")) | true | Compare les contenus, pas l'identité |
Règle d'or : n'utilisez jamais == pour comparer des chaînes. Utilisez equals.
Comparaison insensible à la casse avec equalsIgnoreCase
Lorsque la casse n'a pas d'importance — noms d'utilisateur, extensions de fichiers, noms d'en-têtes — utilisez equalsIgnoreCase :
"Java".equalsIgnoreCase("JAVA"); // trueElle applique la même logique caractère par caractère que equals après avoir normalisé la casse, donc "README".equalsIgnoreCase("readme") est true.
Ordre avec compareTo
Pour trier ou classer des chaînes plutôt que simplement tester leur égalité, utilisez compareTo, qui renvoie le signe de la différence lexicographique (style dictionnaire) :
"apple".compareTo("banana"); // negative — apple comes first
"apple".compareTo("apple"); // 0 — equal
"banana".compareTo("apple"); // positive — banana comes laterUn résultat négatif signifie que le récepteur se classe avant l'argument, 0 signifie égal, positif signifie après. Il existe une variante compareToIgnoreCase, et String.CASE_INSENSITIVE_ORDER à utiliser comme Comparator. Notez que l'ordre par défaut est celui des points de code Unicode, donc toutes les lettres majuscules (A–Z) se classent avant toutes les lettres minuscules.
Un exemple pratique
Ce programme illustre chaque approche côte à côte afin que vous puissiez voir précisément comment chacune se comporte.
Ce qu'il faut retenir de l'exécution :
a == baffichefalsemême si les deux chaînes affichent « java », parce quenew String("java")est un objet distinct — preuve que==compare l'identité, pas le texte.a.equals(b)affichetrue:equalsexamine les caractères, ce qui est presque toujours ce que vous voulez dire par « la même chaîne ».a == caffichetrueuniquement parce que les deux sont des littéraux partageant un objet interné — ce succès accidentel est exactement pourquoi==attire les débutants vers un bug.equalsIgnoreCaseaffichetruepour"Java"vs"JAVA", tandis quecompareTorenvoie0pour un texte identique et un signe non nul (-1pour apple avant banana) lorsqu'ils diffèrent.Objects.equals(null, "x")affichefalsesans lever d'exception, et le tableau trié affiche[Cherry, apple, banana]— leCmajuscule (point de code 67) se classe avant les lettres minuscules (point de code 97+).
Quelle méthode dois-je utiliser ?
Choisissez la comparaison en fonction de la question à laquelle vous répondez réellement :
| Vous voulez savoir… | Utilisez | Notes |
|---|---|---|
| Le texte est-il exactement égal ? | a.equals(b) | Le choix par défaut pour l'égalité |
| Égal, en ignorant les majuscules/minuscules ? | a.equalsIgnoreCase(b) | Normalise la casse d'abord |
Égal, mais l'un ou l'autre peut être null ? | Objects.equals(a, b) | Renvoie true pour deux null, ne lève jamais d'exception |
| Quel est leur ordre de tri ? | a.compareTo(b) | Négatif / 0 / positif |
| Ordre de tri, en ignorant la casse ? | a.compareToIgnoreCase(b) | Ou String.CASE_INSENSITIVE_ORDER comme Comparator |
Une bonne habitude : lorsque vous n'avez besoin que de l'égalité, préférez equals (ou Objects.equals quand null est possible) et jamais compareTo(...) == 0, qui fait strictement plus de travail. Pour explorer les méthodes sur lesquelles celles-ci s'appuient, consultez les méthodes de chaîne Java et la classe String.