2010-12-14 31 views
7

Pour une classe dont les champs sont uniquement primitifs, ex .:Overriding hashCode() - est-ce suffisant?

class Foo 
{ 
    int a; 
    String b; 
    boolean c; 
    long d; 

    boolean equals(Object o) 
    { 
     if (this == o) return true; 
     if (!(o instanceof Foo)) return false; 
     Foo other = (Foo) o; 
     return a == other.a && b.equals(other.b) && c == other.c && d = other.d; 
    } 
} 

Est-ce une façon raisonnable « assez bon » pour écrire hashCode()?

boolean hashCode() 
{ 
    return (b + a + c + d).hashCode(); 
} 

C'est, je construis un String sur les mêmes champs que equals() utilisations, puis il suffit d'utiliser String#hashCode(). J'ai modifié ma question pour inclure un champ long. Comment traiter un long dans hashCode()? Laissez-le simplement déborder int?

+0

Bien qu'il ne soit pas très efficace, il devrait fonctionner correctement car deux instances ayant toutes les mêmes valeurs internes auront le même code de hachage. – Gabe

+0

Cela fonctionnera correctement je ne sais pas sur le problème de performance à ce sujet, mais il va certainement fonctionner. Si vous voulez aller plus loin, lisez: http://www.ibm.com/developerworks/java/library/j-jtp05273.html – Necronet

+0

Utilisez simplement [HashCodeBuilder de commons-lang] (http://commons.apache.org/ lang/api-2.5/org/apache/commons/lang/builder/HashCodeBuilder.html) et ne jamais avoir à se soucier de ce genre de chose –

Répondre

7

Votre code de hachage satisfait la propriété que si deux objets sont égaux, leurs codes de hachage doivent être égaux. Donc, de cette façon, c'est «assez bon». Cependant, il est assez simple de créer des collisions dans les codes de hachage qui vont dégrader les performances des structures de données basées sur le hachage.

je mettre en œuvre un peu différemment si:

public int hashCode() { 
    return a * 13 + b.hashCode() * 23 + (c? 31: 7); 
} 

Vous devriez vérifier les documentation for the hashCode() method de Object. Il énonce les choses que le code de hachage doit satisfaire.

+0

Je comprends le contrat pour 'equals()' et 'hashCode()'. Ce que je cherche est un moyen minimal-effort, idiot-résistant, sans surprise pour accomplir le contrat. Votre code semble assez raisonnable. Pourriez-vous expliquer la raison de la multiplication par les nombres premiers? Aussi, j'ai mis à jour ma question: comment puis-je traiter les champs 'long'? –

+3

@Matt - Le chemin "effort minimum", "idiot résistant" utilise votre IDE pour générer la méthode, par exemple Netbeans génère pour une de mes classes: 'has hash = 5; hash = 37 * hash + (int) (this. id^(this.id >>> 32)); return hash; ' –

+1

@Coronatus: hmm, bon point J'ai oublié' Alt + Shift + S' (Eclipse) –

0

Tout dépend de l'apparence de vos données. Dans la plupart des cas, ce serait une bonne approche. Si vous avez souvent b fin avec un nombre, alors vous obtiendrez des codes en double pour les objets inégaux, comme le montre la réponse de JacobM. Si vous savez à l'avance que b n'aura pratiquement jamais de valeur numérique à la fin, alors c'est un algorithme de hachage raisonnable.