JavaRush /Blog Java /Random-FR /Égal à Java et comparaison de chaînes - Comparaison de ch...

Égal à Java et comparaison de chaînes - Comparaison de chaînes

Publié dans le groupe Random-FR
Bonjour! Aujourd'hui, nous allons parler d'un sujet très important et intéressant, à savoir la comparaison d'objets entre eux avec égal() en Java. Et en effet, dans quels cas en Java l'Objet A sera -t-il égal à l'Objet B ? Comparaison d'égalités et de chaînes - 1Essayons d'écrire un exemple :
public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {

       Car car1 = new Car();
       car1.model = "Ferrari";
       car1.maxSpeed = 300;

       Car car2 = new Car();
       car2.model = "Ferrari";
       car2.maxSpeed = 300;

       System.out.println(car1 == car2);
   }
}
Sortie de la console :

false
D'accord, arrête. Pourquoi, en fait, ces deux voitures ne sont-elles pas égales ? Nous leur avons donné les mêmes propriétés, mais le résultat de la comparaison est faux. La réponse est simple. L'opérateur ==ne compare pas les propriétés des objets, mais les liens. Même si deux objets possèdent 500 propriétés identiques, le résultat de la comparaison sera toujours faux. Après tout, les liens car1pointent car2 vers deux objets différents , vers deux adresses différentes. Imaginez une situation où l'on compare des personnes. Il existe probablement une personne dans le monde qui porte le même nom, la même couleur des yeux, le même âge, la même taille, la même couleur de cheveux, etc. Autrement dit, vous êtes semblables à bien des égards, mais vous n’êtes toujours pas des jumeaux, et surtout pas la même personne. Comparaison d'égalités et de chaînes - 2L'opérateur applique à peu près la même logique ==lorsque nous l'utilisons pour comparer deux objets. Mais que se passe-t-il si vous avez besoin d’une logique différente dans votre programme ? Par exemple, si votre programme simule une analyse ADN. Elle doit comparer le code ADN de deux personnes et déterminer qu'elles sont jumelles.
public class Man {

   int dnaCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = 1111222233;

       Man man2 = new Man();
       man2.dnaCode = 1111222233;

       System.out.println(man1 == man2);
   }
}
Sortie de la console :

false
C’est logique que le résultat soit le même (après tout, nous n’avons rien changé), mais là, nous n’en sommes pas contents ! En effet, dans la vraie vie, l’analyse ADN est une garantie à cent pour cent que nous sommes face à des jumeaux. Mais notre programme et notre opérateur ==nous disent le contraire. Comment pouvons-nous changer ce comportement et garantir que si les tests ADN correspondent, le programme produira le bon résultat ? À cette fin, une méthode spéciale a été créée en Java - equals() .

Méthode Equals() en Java

Comme la méthode toString()dont nous avons parlé plus tôt, equals() appartient à la classe, Objectla classe la plus importante en Java, dont toutes les autres classes sont dérivées. Cependant, equals() lui-même ne changera en rien le comportement de notre programme :
public class Man {

   String dnaCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = "111122223333";

       Man man2 = new Man();
       man2.dnaCode = "111122223333";

       System.out.println(man1.equals(man2));
   }
}
Sortie de la console :

false
Exactement le même résultat, alors pourquoi cette méthode est-elle nécessaire alors ? :/ C'est simple. Le fait est que nous utilisons maintenant cette méthode telle qu'elle est implémentée dans la classe elle-même Object. Et si nous entrons dans le code de la classe Objectet regardons comment cette méthode y est implémentée et ce qu'elle fait, nous verrons :
public boolean equals(Object obj) {
   return (this == obj);
}
C'est la raison pour laquelle le comportement de notre programme n'a pas changé ! À l’intérieur de la méthode equals() de la classe Objectse trouve la même comparaison de référence, ==. Mais l’astuce de cette méthode est que nous pouvons la remplacer. Remplacer signifie écrire votre propre méthode equals() dans notre classe Manet la faire se comporter comme nous le souhaitons ! Nous ne sommes pas convaincus que le contrôle man1.equals(man2)fasse essentiellement la même chose que man1 == man2. Voici ce que nous ferons dans cette situation :
public class Man {

   int dnaCode;

   public boolean equals(Man man) {
       return this.dnaCode ==  man.dnaCode;
   }

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = 1111222233;

       Man man2 = new Man();
       man2.dnaCode = 1111222233;

       System.out.println(man1.equals(man2));

   }
}
Sortie de la console :

true
Un résultat complètement différent ! En écrivant notre propre méthode equals() au lieu de la méthode standard, nous avons obtenu le comportement correct : désormais, si deux personnes ont le même code ADN, le programme nous dit : « L'analyse ADN a montré qu'ils sont jumeaux » et renvoie vrai ! En remplaçant la méthode equals() dans vos classes, vous pouvez facilement créer la logique de comparaison d'objets nécessaire. Nous n'avons abordé la comparaison d'objets qu'en termes généraux. Nous aurons encore une grande conférence séparée sur ce sujet à l'avance (vous pouvez la lire rapidement maintenant, si vous êtes intéressé).

Comparaison de chaînes en Java - Comparaison de chaînes

Pourquoi traitons-nous les comparaisons de chaînes séparément de tout le reste ? Eh bien, en fait, les lignes de programmation sont une toute autre histoire. Premièrement, si vous prenez tous les programmes Java écrits par l’humanité, environ 25 % des objets qu’ils contiennent en sont constitués. Ce sujet est donc très important. Deuxièmement, le processus de comparaison de chaînes est vraiment très différent de celui des autres objets. Regardons un exemple simple :
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}
Sortie de la console :

false
Mais pourquoi faux ? Les lignes sont exactement les mêmes, mot pour mot :/ Vous pouvez le supposer : c'est parce que l'opérateur == compare les références ! Après tout, s1ils s2ont des adresses différentes en mémoire. Si cette pensée vous est venue à l’esprit, reprenons notre exemple :
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = "JavaRush is the best site to learn Java!";
       System.out.println(s1 == s2);
   }
}
Maintenant, nous avons également deux liens, mais le résultat a changé à l'opposé : Sortie de la console :

true
Complètement confus ? :) Voyons cela. L'opérateur ==compare en fait les adresses en mémoire. Cette règle fonctionne toujours et il n’y a aucune raison d’en douter. Cela signifie que si s1 == s2cela renvoie vrai, ces deux chaînes ont la même adresse en mémoire. Et c’est effectivement le cas ! Il est temps de vous familiariser avec une zone mémoire spéciale pour stocker les chaînes - le pool de chaînes ( String pool) Comparaison d'égalités et de chaînes - 3. Le pool de chaînes est une zone pour stocker toutes les valeurs de chaîne que vous créez dans votre programme. Pourquoi a-t-il été créé ? Comme mentionné précédemment, les chaînes occupent une grande partie de tous les objets. Dans tout grand programme, de nombreuses lignes sont créées. Afin d'économiser de la mémoire, c'est ce qui est nécessaire String Pool- une ligne avec le texte dont vous avez besoin y est placée, et à l'avenir, les liens nouvellement créés font référence à la même zone mémoire, il n'est pas nécessaire d'allouer de la mémoire supplémentaire à chaque fois. Chaque fois que vous écrivez String = “........”, le programme vérifie s'il existe une ligne avec un tel texte dans le pool de chaînes. Si tel est le cas, aucun nouveau ne sera créé. Et le nouveau lien pointera vers la même adresse dans le pool de chaînes où cette chaîne est stockée. Par conséquent, lorsque nous avons écrit dans le programme
String s1 = "JavaRush is the best site to learn Java!";
String s2 = "JavaRush is the best site to learn Java!";
le lien s2pointe exactement au même endroit que s1. La première commande a créé une nouvelle ligne dans le pool de chaînes avec le texte dont nous avions besoin, et quand il s'agissait de la seconde, elle faisait simplement référence à la même zone mémoire que s1. Vous pouvez créer au moins 500 lignes supplémentaires avec le même texte, le résultat ne changera pas. Arrêt. Mais pourquoi cet exemple n’a-t-il pas fonctionné pour nous plus tôt ?
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}
Je pense que, intuitivement, vous devinez déjà quelle en est la raison :) Essayez de deviner avant de poursuivre la lecture. Vous pouvez voir que ces deux lignes ont été créées différemment. L'un est avec l'aide de l'opérateur newet le second sans celui-ci. C'est précisément la raison. L'opérateur new, lors de la création d'un objet, lui alloue de force une nouvelle zone en mémoire . Et la ligne créée avec new, ne finit pas dans String Pool: elle devient un objet à part entière, même si son texte est exactement le même que la même ligne de String Pool'a. Autrement dit, si nous écrivons le code suivant :
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = "JavaRush is the best site to learn Java!";
       String s3 = new String("JavaRush is the best site to learn Java!");
   }
}
En mémoire, cela ressemblera à ceci : Comparaison d'égalités et de chaînes - 4Et à chaque fois qu'un nouvel objet est créé, newune nouvelle zone sera allouée en mémoire, même si le texte à l'intérieur des nouvelles lignes est le même ! Il semble que nous ayons réglé le problème de l'opérateur ==, mais qu'en est-il de notre nouvel ami, la méthode equals() ?
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1.equals(s2));
   }
}
Sortie de la console :

true
Intéressant. Nous savons exactement quoi s1et s2pointons vers différentes zones de la mémoire. Mais néanmoins, la méthode equals() indique qu’ils sont égaux. Pourquoi? Rappelez-vous, nous avons dit ci-dessus que la méthode equals() peut être remplacée dans votre classe afin qu'elle compare les objets comme vous en avez besoin ? C'est ce qu'ils ont fait avec la classe String. Il a une méthode equals() remplacée. Et il ne compare pas les liens, mais plutôt la séquence de caractères dans les chaînes. Et si le texte des chaînes est le même, peu importe comment elles ont été créées et où elles sont stockées : dans le pool de chaînes ou dans une zone mémoire séparée. Le résultat de la comparaison sera vrai. À propos, Java vous permet de comparer correctement les chaînes sans tenir compte de la casse. Dans une situation normale, si vous écrivez une des lignes, par exemple, en majuscules, le résultat de la comparaison sera faux :
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JAVARUSH - ЛУЧШИЙ САЙТ ДЛЯ ИЗУЧЕНИЯ JAVA!");
       System.out.println(s1.equals(s2));
   }
}
Sortie de la console :

false
Dans ce cas, la classe Stringa une méthode equalsIgnoreCase(). Si l'essentiel de votre comparaison est la séquence de caractères spécifiques, et non leur casse, vous pouvez l'utiliser. Par exemple, cela sera utile pour comparer deux adresses e-mail :
public class Main {

   public static void main(String[] args) {

       String address1 = "Moscow, Academician Korolev street, 12";
       String address2 = new String("Г. МОСКВА, УЛ. АКАДЕМИКА КОРОЛЕВА, ДОМ 12");
       System.out.println(address1.equalsIgnoreCase(address2));
   }
}
Dans ce cas, il est évident que nous parlons de la même adresse, utiliser cette méthode equalsIgnoreCase()sera donc la bonne décision.

Méthode String.intern()

La classe Stringa une autre méthode délicate -intern() ; La méthode intern()fonctionne directement avec String Pool'om. Si vous appelez une méthode intern()sur une chaîne, cela :
  • Cherche s'il existe une chaîne avec ce texte dans le pool de chaînes
  • Si tel est le cas, renvoie un lien vers celui-ci dans le pool
  • Sinon, il place une ligne avec ce texte dans le pool de chaînes et renvoie un lien vers celle-ci.
En appliquant la méthode intern()à la référence de chaîne créée via new, nous pouvons la comparer avec la référence de chaîne de String Pool'a via le ==.
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2.intern());
   }
}
Sortie de la console :

true
Auparavant, lorsque nous les comparions sans intern(), le résultat était faux. Maintenant, la méthode intern()vérifiait s'il y avait une ligne avec le texte "JavaRush - le meilleur site pour apprendre Java !" dans le pool de chaînes. Bien sûr qu'il est là : nous l'avons créé lorsque nous avons écrit
String s1 = "JavaRush is the best site to learn Java!";
Il a été vérifié que la référence s1et la référence renvoyée par la méthode s2.intern()pointent vers la même zone en mémoire, et, bien sûr, c'est le cas :) Pour résumer, retenez et utilisez la règle principale : Pour comparer des chaînes, utilisez TOUJOURS la fonction égale(). méthode! Lorsque vous comparez des chaînes, vous entendez presque toujours comparer leur texte, et non les liens, les zones de mémoire, etc. La méthode equals() fait exactement ce dont vous avez besoin. Voici quelques liens pour étudier par vous-même :
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION