Edit: Préparez mes objets pour l'utilisation dans un hachema. P>
Après avoir lu un peu la façon de générer un code de hachage, je suis un type de confusion maintenant. Ma question (probablement triviale) est, comment dois-je mettre en œuvre une méthode de code HASHCODE lorsque j'ai un seul domaine que je pourrais utiliser? Puis-je utiliser les fiels directement? Si je comprends bien correctement, les valeurs de HashCode ne doivent pas changer pendant la durée de vie d'un objet, et je n'ai qu'un identifiant déposé qui correspond à cela, mais j'ai lu ailleurs, que l'on ne devrait pas utiliser ID ... Des despides de cela, comment Une fonction hashcode serait-elle basée sur celle-ci (une valeur unique et non changeante)? La méthode Equals est également basée sur l'identifiant uniquement .. p>
3 Réponses :
Si votre objet est mutable, il est acceptable de modifier son code de hachage au fil du temps. Bien sûr, vous devriez préférer des objets immuables ( Efficace Java 2nd édition, point 15: minimiser l'utabilité em>). Voici la recette de hashcode de Josh Bloch, de Efficient Java 2nd Edition, point 9 : Toujours remplacer Il serait correct de suivre la recette tel quel, même avec un seul champ. Faites juste l'action appropriée en fonction du type de champ. P> Notez qu'il existe des bibliothèques qui simplifient cela pour vous, par exemple. Ces bibliothèques vous permettent de simplement écrire quelque chose comme ceci: p> hashcode code> lorsque vous remplacez
égale code> em>: p>
Recette de code de hachage Java 2nd édition efficace h3>
int code> appelé
résultat code>. li>.
int code> hashcode
C code> pour chaque champ:
booléen code>, calculez
(f? 1: 0) code> li>
octet, char, court, int code>, calculez
(int) f code> li>
long code>, calculez
(int) (f ^ (f >>> 32)) code> li>
float code>, calculez
float.floattingbits (f) code> li>
double code>, calculez
double.doubletolongbits (f) code>, puis hachage le
long code> comme dans ci-dessus. li>
de cette classe est égale code> compare le champ en appelant de manière récursive
égale code>, invoquer de manière récursive
hashcode code> sur le champ . Si la valeur du champ est
null code>, retour 0. li>
TRAASAYS.HASTCODE CODE> Ajouté dans la version 1.5. LI>
ul> li>
C code> dans
résultat code> comme suit:
résultat = 31 * résultat + c; code> li> li>
ul>
hashcodebuilder code> de Apache Commons Lang ou juste
arrairies.hashscode / deevhashCode code> de
java.util.arrays code>
. p> import org.apache.commons.lang.builder.*;
public class CustomType implements Comparable<CustomType> {
// constructors, etc
// let's say that the "significant" fields are field1, field2, field3
@Override public String toString() {
return new ToStringBuilder(this)
.append("field1", field1)
.append("field2", field2)
.append("field3", field3)
.toString();
}
@Override public boolean equals(Object o) {
if (o == this) { return true; }
if (!(o instanceof CustomType)) { return false; }
CustomType other = (CustomType) o;
return new EqualsBuilder()
.append(this.field1, other.field1)
.append(this.field2, other.field2)
.append(this.field3, other.field3)
.isEquals();
}
@Override public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(field1)
.append(field2)
.append(field3)
.toHashCode();
}
@Override public int compareTo(CustomType other) {
return new CompareToBuilder()
.append(this.field1, other.field1)
.append(this.field2, other.field2)
.append(this.field3, other.field3)
.toComparison();
}
}
+1 pour cette réponse informative sur HashCode et la suggestion de tableau.Hashcode (); Première fois que j'ai vu ça et j'aime ça!
Merci encore pour cette longue et bonne réponse compréhensible. Mais j'ai manqué d'autres points - pour l'instant, je n'ai pas à mettre en œuvre un hashcode (voir Michaels Commentaire), mais peut-être que je dois à l'avenir, votre réponse est donc trop tôt à temps. ;)
Depuis Java SE 7, vous pouvez utiliser Objets # Hash (objet ...) .
Veuillez ajouter la raison pour laquelle nous devons multiplier chaque hachage de valeur calculée précédente, c'est une information agréable.
Si vous voulez que des objets avec différents identifiants identifiés par cet identifiant, tout ce que vous avez à faire est de le renvoyer / le comparer.
private final int id; public int hashCode() { return id; } public boolean equals(Object o) { return o instanceof ThisClass && id == ((ThisClass)o).id; }
Votre fonction Equals n'est pas implémentée de la manière correcte, mais simplement de retourner l'identifiant comme hashvalue, je compte comme réponse à ma question, donc +1.
Quel est le problème avec les égaux ()? Si seul le champ d'identification est suffisant pour remplacer HashCode (), Peters Equals () La mise en œuvre semble parfaitement bien.
@KRMBY HM, AFAIK Il doit y avoir un chèque nul afin qu'il retourne faux dans ce cas.
L'instanceof fera le Nullcheck pour vous. Cela est égal () est moche, mais semble être correct.
Peu importe que le nombre de champs sont utilisés pour calculer HashCode.
Mais il compte travailler avec Si vous détestez HashCode :) et votre objet ne sera jamais mis aux conteneurs à base de hash (HASHMAP, HASHSET ..), il suffit de quitter HashCode () seul, laissez la classe de base à calculer HashCode. P>
Bon point, vous n'avez pas besoin d'implémenter des égaux / HashCode pour la plupart des objets.
Je demande parce que j'utilise maintenant un hashmap pour obtenir le O (1) fois pour obtenir une entrée.
@Insernickhere: Désolé d'avoir mal lu votre question. Assurez-vous que votre objet est mis sur HASHMAP comme clé pas une valeur.
Oh, tu vois, tu m'as signalé quelque chose que je me trompe totalement. Je pensais que je dois écrire du code de hasch Evan si j'utilise ma classe comme des valeurs. D'Oh, à quel point puis-je être stupide? ;-)
@Poly si j'ai bien compris correction, comme IIRC, si je me souviens bien.
L'ambiguïté de IIC a décidé de "si je me souviens bien".