498 votes

Pourquoi ai-je besoin de substituer equals et hashCode méthodes en Java ?

Récemment j’ai lu ce Document Works développeur. Le document est tout au sujet de définir et efficacement et correctement, mais je ne suis pas en mesure de comprendre pourquoi nous devons substituer ces deux méthodes.

Comment est-ce que je peux prendre la décision de mettre en œuvre ces méthode efficacement ?

664voto

Lombo Points 2764

Il n'est pas toujours nécessaire de remplacer hashcode et equals. Mais si vous pensez que vous avez besoin pour remplacer l'un, alors vous avez besoin de remplacer tous les deux. Nous allons analyser ce qui devrait arriver si nous remplacer l'un mais pas l'autre et nous essayons d'utiliser un Map.

Disons que nous avons une classe de ce genre et que les deux objets d' MyClass sont égales si leurs importantField est égal (avec hashCode et equals généré par eclipse)

public class MyClass {

    private final String importantField;
    private final String anotherField;

    public MyClass(final String equalField, final String anotherField) {
        this.importantField = equalField;
        this.anotherField = anotherField;
    }

    public String getEqualField() {
        return importantField;
    }

    public String getAnotherField() {
        return anotherField;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((importantField == null) ? 0 : importantField.hashCode());
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        final MyClass other = (MyClass) obj;
        if (importantField == null) {
            if (other.importantField != null)
                return false;
        } else if (!importantField.equals(other.importantField))
            return false;
        return true;
    }

}

Remplacer uniquement hashCode

Imaginez que vous avez ce

MyClass first = new MyClass("a","first");
MyClass second = new MyClass("a","second");

Si vous n'ignorer hashCode puis quand vous appelez myMap.put(first,someValue) il prend tout d'abord, calcule ses hashCode et les stocke dans un seau. Ensuite, lorsque vous appelez myMap.put(second,someOtherValue) il devrait remplacer la première avec la seconde que par la Carte de la Documentation parce qu'ils sont égaux (selon notre définition).

Mais le problème est que est égal n'a pas été redéfini, de sorte que lorsque la carte hachages second et parcourt le seau en regardant si il y a un objet k tels que second.equals(k) est vrai qu'elle ne trouverez pas en tant que second.equals(first) sera false.

Remplacer uniquement equals

Si seulement equals est surchargé, puis quand vous appelez myMap.put(first,someValue) premier sera de hachage pour seau et lorsque vous appelez myMap.put(second,someOtherValue) il va de hachage à un autre seau (car ils ont un autre hashCode). Donc, même s'ils sont égaux, car ils ne font pas de hachage pour le même seau, la carte ne peut pas la réaliser et à la fois de leur séjour à la carte.

Espère que c'était clair

54voto

JuanZe Points 4519

Il est nécessaire de redéfinir hashCode() dans tous les classe qui remplace equals(). L'échec pour le faire se traduira par une violation de les conditions générales du contrat pour Objet.hashCode(), qui permettra d'éviter l' votre classe de fonctionner correctement en collaboration avec tous les base de hachage collections, y compris la table de hachage, HashSet, et de la table de hachage.


de Efficace Java, par Joshua Bloch

Par définition equals() et hashCode (), de manière cohérente, vous pouvez améliorer la convivialité de vos classes comme des clés dans la base de hachage collections. Comme la doc API pour hashCode explique: "Cette méthode est prise en charge pour le bénéfice des tables de hachage, tels que ceux fournis par java.util.Table de hachage."

La meilleure réponse à votre question sur la façon de mettre en œuvre ces méthodes de manière efficace en vous proposant de lire le Chapitre 3 de l' Effectif de Java.

26voto

crunchdog Points 3068

Tout simplement, l'égalité de la méthode dans l'Objet de vérifier la référence de l'égalité, où deux instances de votre classe pourrait encore être sémantiquement équivalents lorsque les propriétés sont égaux. C'est par exemple important lors de la mise de vos objets dans un récipient qui utilise equals et hashcode, comme HashMap et Ensemble. Disons que nous avons une classe comme:

public class Foo {
    String id;
    String whatevs;

    Foo(String id, String whatevs) {
        this.id = id;
        this.whatevs = whatevs;
    }
}

Nous allons créer deux instances avec les mêmes id:

Foo a = new Foo("id", "something");
Foo b = new Foo("id", "something else");

Sans primordial est égal, nous obtenons:

  • un.est égal à(b) est faux car ils sont deux instances différentes
  • un.est égal à(a) est vrai car c'est la même instance
  • b.est égal à(b) est vrai car c'est la même instance

- Il Correct? Eh bien peut-être, si c'est ce que vous voulez. Mais disons que nous voulons objets avec le même id pour le même objet, qu'il s'agisse de deux instances différentes. Nous remplacer la equals (et hashcode):

public class Foo {
    String id;
    String whatevs;

    Foo(String id, String whatevs) {
        this.id = id;
        this.whatevs = whatevs;
    }

    @Override
    public boolean equals(Object other) {
        if (other instanceof Foo) {
            return ((Foo)other).id.equals(this.id);   
        }
    }

    @Override
    public int hashCode() {
        return this.id.hashCode();
    }
}

Comme pour la mise en œuvre equals et hashcode je peux vous recommandons d'utiliser la Goyave l'aide de méthodes

7voto

PaulJWilliams Points 11641

Parce que si vous ne substituez pas eux vous utiliserez la Startégie de défaut dans l’objet.

Étant donné que les valeurs d’égalité et hascode instance exigent généralement la connaissance de ce qui constitue un objet qu’ils devront généralement être redéfini dans votre classe ait un sens concret.

6voto

Prashanth Points 51

Afin d’utiliser nos propres objets de la classe en tant que clés dans des anthologies comme HashMap, Hashtable etc... , nous devons substituer les deux méthodes (hashCode() et equals()) par la présence d’une prise de conscience sur le fonctionnement interne de la collection. Dans le cas contraire, elle conduit à des résultats erronés qui nous ne sommes pas attendus.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X