JavaRush /Blog Java /Random-FR /Travailler avec les méthodes hashCode() et equals() en Ja...
Lenchik854
Niveau 0
Chernihiv

Travailler avec les méthodes hashCode() et equals() en Java

Publié dans le groupe Random-FR
Dans cet article, je décrirai ma compréhension des méthodes hashCode()et equals(). Je veux parler de leur implémentation par défaut, ainsi que de la façon de les remplacer correctement. J'écrirai également sur l'implémentation de ces méthodes à l'aide des classes d'assistance du package Apache Common. Travailler avec les méthodes hashCode() et equals() en Java - 1Contenu de cet article :
  1. En utilisant hashCode()et equals().
  2. Remplacez le comportement par défaut.
  3. Remplacement hashCode()et equals()utilisation d'Apache Commons Lang.
  4. Quelque chose dont il est important de se souvenir.
  5. Attention particulière lors de l'utilisation d'ORM.
Les méthodes hashCode()et equals()ont été définies dans la classe Object, qui est la classe parent des objets Java. Par conséquent, tous les objets Java héritent de l’implémentation par défaut de ces méthodes.

Utiliser hashCode() et equals()

La méthode hashCode()est utilisée pour obtenir un nombre entier unique pour un objet donné. Lorsqu'un objet doit être stocké sous forme de structure de données dans une table de hachage (également appelée compartiment), ce numéro est utilisé pour déterminer son emplacement dans cette table. Par défaut, la méthode hashCode()d'un objet renvoie le numéro de l'emplacement mémoire où l'objet est stocké. La méthode equals(), comme son nom l'indique, permet de vérifier simplement l'égalité de deux objets. L'implémentation par défaut de cette méthode vérifie simplement les références de deux objets pour voir si elles sont équivalentes.

Remplacement du comportement par défaut

Tout fonctionne bien tant que vous ne remplacez aucune de ces méthodes dans vos cours. Mais parfois, les applications doivent modifier le comportement par défaut de certains objets. Prenons un exemple où vous avez un Employee. Écrivons la structure minimale possible d'une telle classe.
public class Employee
{
    private Integer id;
    private String firstname;
    private String lastName;
    private String department;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getFirstname() {
        return firstname;
    }
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }
}
La classe décrite ci-dessus Employeepossède quelques attributs de base et méthodes d'accès. Examinons maintenant une situation simple dans laquelle nous devons comparer deux objets de la classe Employee.
public class EqualsTest {
    public static void main(String[] args) {
        Employee e1 = new Employee();
        Employee e2 = new Employee();

        e1.setId(100);
        e2.setId(100);
        //Печатает false в консоли
        System.out.println(e1.equals(e2));
    }
}
Il n’est pas nécessaire d’être clairvoyant pour deviner que la méthode ci-dessus renverra « faux ». Mais est-ce réellement exact, étant donné que ces deux objets sont identiques ? Dans une application en temps réel, la méthode doit renvoyer true. Pour obtenir le comportement correct, nous devons remplacer la méthode equals(), comme suit :
public boolean equals(Object o) {
        if(o == null)
        {
            return false;
        }
        if (o == this)
        {
           return true;
        }
        if (getClass() != o.getClass())
        {
            return false;
        }
        Employee e = (Employee) o;
        return (this.getId() == e.getId());
}
Ajoutez cette méthode à votre classe Employeeet la vérification d'équivalence renverra « vrai ». Cependant, avons-nous tout fait ? Pas encore. Testons notre classe modifiée d'une autre manière.
import java.util.HashSet;
import java.util.Set;

public class EqualsTest
{
    public static void main(String[] args)
    {
        Employee e1 = new Employee();
        Employee e2 = new Employee();

        e1.setId(100);
        e2.setId(100);

        //Печатает 'true'
        System.out.println(e1.equals(e2));

        Set employees = new HashSet();
        employees.add(e1);
        employees.add(e2);
        //Печатает два an object
        System.out.println(employees);
    }
}
La commande System.out.println(employee)imprime deux objets. Si les deux objets étaient équivalents et que Setseuls des objets uniques étaient contenus, alors HashSetil ne devrait y avoir qu'une seule instance à l'intérieur, c'est-à-dire les deux objets font référence aux mêmes instances de la classe Employee. Qu’avons-nous manqué ? Nous avons raté la deuxième méthode importante hashCode(). Comme le dit la documentation Java, si vous remplacez la méthode equals(), vous devez alors remplacer la méthode hashCode(). Alors ajoutons une autre méthode à notre classe Employee.
@Override
 public int hashCode()
 {
    final int PRIME = 31;
    int result = 1;
    result = PRIME * result + getId();
    return result;
 }
Nous avons ajouté cette méthode une fois à notre classe, et un seul objet sera imprimé, et ainsi, la vérification de l'équivalence de e1 et e2 s'est avérée vraie.

Remplacement hashCode()et equals()utilisation d'Apache Commons Lang

Apache Commons fournit deux excellentes classes d'assistance pour appeler des méthodes hashCode()et equals(). Ci-dessous, nous voyons l'utilisation:
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
public class Employee
{
 private Integer id;
 private String firstname;
 private String lastName;
 private String department;
public Integer getId() {
    return id;
 }
 public void setId(Integer id) {
    this.id = id;
 }
 public String getFirstname() {
    return firstname;
 }
 public void setFirstname(String firstname) {
    this.firstname = firstname;
 }
 public String getLastName() {
    return lastName;
 }
 public void setLastName(String lastName) {
    this.lastName = lastName;
 }
 public String getDepartment() {
    return department;
 }
 public void setDepartment(String department) {
    this.department = department;
 }
@Override
 public int hashCode()
 {
    final int PRIME = 31;
    return new HashCodeBuilder(getId()%2==0?getId()+1:getId(), PRIME).
           toHashCode();
 }
@Override
 public boolean equals(Object o) {
    if (o == null)
       return false;
    if (o == this)
       return true;
    if (o.getClass() != getClass())
       return false;
    Employee e = (Employee) o;
       return new EqualsBuilder().
              append(getId(), e.getId()).
              isEquals();
    }
 }
D'un autre côté, si vous utilisez l'un des éditeurs de code, ils devraient également pouvoir appeler de jolies structures pour vous. Par exemple, si dans l'IDE Eclipse vous cliquez avec le bouton droit sur class >> source > Génération de hashCode() et equals()... cela générera une très belle implémentation pour vous. Travailler avec les méthodes hashCode() et equals() en Java - 2Quelque chose dont il est important de se souvenir.
  1. Utilisez toujours les mêmes attributs d'objet pour appeler à la fois and hashCode()et equals(). Juste dans notre cas, nous avons utilisé employee id.
  2. La méthode equals()doit être persistante (si l'objet n'a pas changé, la méthode doit renvoyer la même valeur).
  3. À chaque fois a.equals(b), alors a.hashCode()doit être identique à b.hashCode().
  4. Si vous remplacez une méthode, vous devez remplacer la seconde.

Attention particulière lors de l'utilisation d'ORM

Si vous utilisez ORM (ru.wikipedia.org/wiki/ORM), utilisez toujours des getters et n'utilisez jamais de références de champ hashCode(). equals()En effet, dans un ORM, les champs sont de temps en temps chargés à l'aide d'un chargement paresseux et ne sont pas accessibles tant que leurs getters ne sont pas appelés. Par exemple, dans notre classe Employee, nous utilisons e1.id == e2.id. Il est tout à fait possible que les ichamps d soient chargés en utilisant un chargement paresseux. L'un des champs peut être 0 ou nul et nous obtiendrons un comportement incorrect. Mais, si , est utilisé e1.getId() == e2.getId(), nous pouvons en être sûrs même si les champs ont été chargés en utilisant le chargement paresseux ; appeler le getter remplira le champ en premier. C'est tout ce que je sais sur les méthodes hashCode()and equals(). J'espère que cela aide quelqu'un quelque part. Bonne chance dans tes études !! ps C'est ma première tentative de traduction. J'ai essayé de tout transmettre le plus près possible de ce que l'auteur voulait dire. Si vous avez des commentaires, veuillez l'écrire dans les commentaires. Ne jugez pas strictement :-))) Article original
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION