Ce document est une réimpression du matériel créé pour les nouveaux ingénieurs il y a environ 10 ans. Certaines parties démodées telles que l'API et la syntaxe peuvent être perceptibles, mais une fois que vous avez compris l'idée, j'ai l'intention d'organiser les parties de base qui peuvent être utilisées pendant longtemps, j'espère donc que cela sera utile pour les jeunes ingénieurs maintenant.
--Comprendre la différence entre l'opérateur d'égalité "==" et la méthode equals en Java
En supposant que la classe User existe comme indiqué ci-dessous, lisez la suite. La classe User conserve son ID et son nom en tant qu'état interne.
User.java
class User {
/** ID */
private int id;
/**Nom*/
private String name;
/**
*C'est un constructeur.
*
* @param id ID
* @nom du paramètre nom
*/
public User(int id, String name) {
this.id = id;
this.name = name;
}
//Omis ci-dessous
}
User user1 = new User(1, "Tanaka");
User user2 = user1;
user1 et user2 contiennent des références au même objet. Par conséquent, les objets référencés par user1 et user2 sont "identiques".
User user3 = new User(1, "Tanaka");
User user4 = new User(2, "Suzuki");
User user5 = new User(1, "Suzuki");
user3 et user5 ont le même ID. user4 et user5 ont le même nom.
Par conséquent, user3 et user5 sont des objets avec "valeur égale" dans la valeur d'ID. user4 et user5 sont des objets avec des «valeurs égales» dans leurs valeurs de nom.
L'équivalence d'objet doit être implémentée par le programmeur lui-même selon les règles métier.
L'équivalence d'objet est définie dans la méthode equals de la classe appropriée.
S'il existe une règle pour juger de l'équivalence de l'objet de classe User dans la valeur ID, décrivez le processus de comparaison de la valeur ID dans la méthode equals.
S'il existe une règle pour juger de l'équivalence de l'objet de la classe User dans la valeur de nom, décrivez le processus pour comparer la valeur de nom dans la méthode equals.
L'identité de l'objet est déterminée par l'opérateur de comparaison "==". Puisque user1 et user2 ci-dessus sont le même objet
user1 == user2 // ⇒ true
Le résultat de est "vrai".
Parce que user3, user4 et user5 sont tous des objets différents
user3 == user4 // ⇒ false
user3 == user5 // ⇒ false
user4 == user5 // ⇒ false
Le résultat de est tout "faux".
L'égalité des objets est comparée par la méthode "equals" implémentée dans chaque classe.
Si la méthode equals de la classe User est implémentée avec l'ID comme condition de comparaison, le résultat de la méthode equals est le suivant.
user3.equals(user4) // ⇒ false
user3.equals(user5) // ⇒ true
user4.equals(user5) // ⇒ false
Si la méthode equals de la classe User est implémentée avec le nom comme condition de comparaison, le résultat de la méthode equals est le suivant.
user3.equals(user4) // ⇒ false
user3.equals(user5) // ⇒ false
user4.equals(user5) // ⇒ true
Pour déterminer l'équivalence d'objet de la classe User par ID, implémentez la méthode equals dans la classe User comme suit.
User.java
/**
*L'instance de cette classe et l'objet passé en argument
*Renvoie vrai s'ils sont égaux.
*L'objet passé en argument est une instance de la classe User
*Si les valeurs id sont égales, elles sont considérées comme égales.
*
* @Vrai si l'objet passé dans l'argument de retour est une instance de la classe User et que les identifiants sont égaux.
*/
public boolean equals(Object other) {
if (this == other) { //Vrai si l'objet passé dans l'argument était cet objet lui-même
return true;
}
if (!(other instanceof User)) { //L'objet passé en argument est un objet de la classe User
return false; //Faux sinon.
}
User otherUser = (User) other;
if (this.id == otherUser.getId()) { //Comparez les valeurs d'ID, vrai si égal, faux si différent.
return true;
}
return false;
}
Pour déterminer l'équivalence d'objet de la classe User par son nom, implémentez la méthode equals dans la classe User comme suit.
Le reste du processus est le même, seule la comparaison des valeurs change de l'id au nom.
User.java
/**
*L'instance de cette classe et l'objet passé en argument
*Renvoie vrai s'ils sont égaux.
*L'objet passé en argument est une instance de la classe User
*Si les valeurs de name sont égales, elles sont considérées comme égales.
*
* @True si l'objet passé dans l'argument de retour est une instance de la classe User et que les noms sont égaux.
*/
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof User)) {
return false;
}
User otherUser = (User) other;
if (this.name.equals(otherUser.getName())) {
return true;
}
return false;
}
Si vous implémentez la méthode equals, vous devez également implémenter la méthode hashCode. La méthode hashCode est implémentée selon les règles suivantes.
Dans la classe User, si vous implémentez la méthode equals qui détermine l'égalité en fonction de la valeur de l'ID, la méthode hashCode est implémentée comme suit, à titre d'exemple.
User.java
/**
*Renvoie le code de hachage.
*
* @renvoie la valeur de hachage d'une instance de cette classe
*/
public int hashCode() {
return this.id;
}
Dans la méthode equals, l'équivalence est évaluée en fonction de la valeur de l'ID, de sorte que la méthode hashCode de l'objet dont les valeurs d'ID sont égales, c'est-à-dire que la méthode equals renvoie true, retournera la même valeur par l'implémentation ci-dessus. , On peut dire que le traitement de la méthode hashCode ci-dessus est approprié pour la règle ci-dessus.
User.java
/**
*Renvoie le code de hachage.
*
* @renvoie la valeur de hachage d'une instance de cette classe
*/
public int hashCode() {
return 0;
}
Le traitement de la méthode hashCode ci-dessus est en fait valide. Le hashCode pour tous les objets renvoie 0. Autrement dit, tous les objets pour lesquels la méthode equals est true renverront la même valeur (0) que la valeur de retour hashCode. L'implémentation ci-dessus est également considérée comme correcte à la lumière des règles de l'implémentation de hashCode, car il est acceptable pour les objets dont la méthode equals n'est pas vraie (le résultat de l'appel de la méthode equals est faux) de renvoyer la même méthode hashCode. ..
Cependant, la mise en œuvre de l'exemple 2 n'est pas recommandée. Lors de l'implémentation de hashCode, implémentez-le au moins comme dans l'exemple 1.
Si vous ajoutez un objet qui n'implémente pas correctement hashCode à une instance d'une classe qui utilise un algorithme de hachage (HashMap, HashSet, etc.), le comportement attendu ne sera pas obtenu.
Il s'agit d'un algorithme qui rationalise le traitement en calculant la valeur de hachage à l'avance lors du stockage et de la recherche d'objets, et du stockage et de la recherche d'objets en fonction de la valeur de hachage obtenue.
Pour comprendre l'algorithme de hachage, c'est une bonne idée de comparer les différences de comportement entre ArrayList et HashSet.
ArrayList et HashSet sont tous deux des classes qui implémentent l'interface Collection, mais ils présentent les différences de comportement suivantes. (HashSet implémente un algorithme de hachage.)
ArrayList stocke et contient les éléments ajoutés dans une liste à une colonne. Lors de la récupération des éléments stockés, la méthode equals de l'objet est appelée dans l'ordre depuis le début de la liste, et l'élément pour lequel le résultat de l'appel de méthode equals est vrai est renvoyé comme valeur de retour.
⇒ Si le nombre d'éléments dans la liste est énorme et que l'élément que vous voulez récupérer est derrière la liste, l'efficacité de la recherche peut être extrêmement détériorée.
HashSet stocke et récupère les éléments ajoutés selon la procédure suivante.
Étant donné que les éléments sont classés dans des "pièces" en fonction de hashCode à l'avance et stockés, lors de la comparaison d'objets, il est seulement nécessaire de comparer un nombre limité d'objets, ce qui améliore l'efficacité de la recherche.
Si hashCode n'est pas implémenté correctement, il se peut que l'objet cible ne puisse pas être trouvé car l'objet cible est recherché dans une autre pièce même si les objets ont la même valeur.
Si hashCode est implémenté pour retourner 0, tous les objets seront stockés dans la "salle" avec pratiquement le numéro de salle 0, et l'algorithme sera le même que l'ajout d'un élément à ArrayList, qui a l'avantage de l'algorithme de hachage Je ne peux pas comprendre.
Les méthodes equals et hashCode sont à l'origine implémentées dans la classe Object.
La classe Object est une superclasse de toutes les classes. Par conséquent, si vous appelez la méthode equals ou hashCode sur une instance d'une classe qui n'implémente pas les méthodes equals et hashCode, elle sera définie dans la classe Object parente (à moins qu'il n'y ait pas d'autre classe héritière). La méthode equals et la méthode hashCode sont appelées.
Par exemple, si la méthode equals est appelée pour une instance d'une classe qui n'implémente pas la méthode equals, l'ordre d'appel des méthodes est le suivant.
"Implémentation de la méthode equals et de la méthode hashCode" signifie (quand il n'y a pas d'autre classe à hériter)
Cela signifie que.
La méthode equals définie dans la classe Object détermine "l'équivalence d'objet" basée sur "l'identité d'objet".
Par conséquent, si vous n'implémentez pas la méthode equals dans la classe User (sans remplacer la méthode equals dans la classe Object), la méthode equals si l'instance de la classe User n'est ni un ID ni un nom et que les instances sont exactement les mêmes (identiques). Reviendra vrai.
//Comportement de la méthode equals de la classe Object
Object obj1 = new Object();
Object obj2 = new Object();
Object obj3 = obj1;
obj1 == obj2; // false
obj2 == obj3; // false
obj1 == obj3; // true
// "=="La comparaison et les résultats sont les mêmes
obj1.equals(obj2); // false
obj2.equals(obj3); // false
obj1.equals(obj3); // true
//Comportement de la classe User qui n'implémente pas la méthode equals
// (Le comportement est le même car la méthode equals définie dans la classe Object est appelée.)
User user1 = new User();
User user2 = new User();
User user3 = user1;
user1 == user2; // false
user2 == user3; // false
user1 == user3; // true
user1.equals(user2); // false
user2.equals(user3); // false
user1.equals(user3); // true