Qu'est-ce que le hashCode pour une classe personnalisée deux int propriétés?
En Java, j'ai une classe qui représente un point de l'int coordonnées
public class Point {
int x = -1;
int y = -1;
public Point (int xNew, int yNew) {
x = xNew; y = yNew;
}
public boolean equals (Object o) {
//no need for (o instanceof Point) by design
return x == ((Point)o).x && y == ((Point)o).y;
}
}
Je suis en utilisant les objets de la classe Point
comme clés dans un HashMap
et en tant qu'éléments dans un HashSet
.
Quel serait le meilleur candidat pour le hashCode
fonction? Je voudrais faire le double de sorte que la partie de gauche est x et la partie droite est y, par exemple:
x = 4, y = 12
, puis le hashCode
retourne 4.12
. Mais par la mise en œuvre, il ne peut pas être double, seulement int.
Ce n'est pas une option:
public int hashCode() {
//no need to check for exception parseInt since x and y are valid by design
return Integer.parseInt(Integer.toString(x) + Integer.toString(y));
}
parce que les valeurs x
et y
peut être trop long, afin qu'ensemble, ils ne seront pas convertis.
- int hashCode dit de retour pour le hashcode de la méthode est de type int seulement, donc double est exclue.
- Oui, c'est pourquoi je suis restée un certain temps.
Vous devez vous connecter pour publier un commentaire.
Vous ne pouvez pas modifier le type de
hashCode
, ni si vous le souhaitez.Je venais d'aller avec quelque chose comme:
Notez que cela signifie que (a, b) est différent de (b, a) pour la plupart des cas (à la différence par exemple en ajoutant ou XOR-ing). Cela peut être utile si vous finissent souvent avec des touches pour le "sous tension" les valeurs dans la vraie vie.
Il n'est pas unique - mais des codes de hachage n'ont pas à l'être. Ils juste doivent être les mêmes pour les valeurs égales (de justesse), et (pour l'efficacité) "habituellement" différentes pour les non-valeurs égales, avec une répartition raisonnable.
En général, j'ai l'habitude de suivre le même type de schéma que Josh Bloch suggère Effective Java:
Où
field1Hash
serait le code de hachage de référence pour les champs de type (ou 0 pour une référence nulle), laint
lui-même pour les valeurs int, une sorte de hachage à partir de 64 bits à 32 pourlong
etc.EDIT: je ne me souviens pas des détails de pourquoi le 31 et 17 ans travaillent bien ensemble. Le fait qu'ils sont à la fois premier peut être utile - mais de ce que je me souviens, les mathématiques derrière pourquoi les hachages de ce genre sont généralement raisonnable (bien que pas aussi bon que les hachages où la distribution des valeurs probables est connu à l'avance) est difficile ou pas bien comprise. Je sais que le fait de multiplier par 31 est bon marché (maj gauche 5 et soustraire la valeur d'origine)...
hash *= 31 + field1Hash
au lieu dehash = hash * 31 + field1Hash
. NE PAS le faire. Il modifie l'ordre des opérateurs comme la partie après le *= est évalué en premier, puis multipliés avec le courant de hachage. Juste mon 5 centimes d'avertissement pour les gens de "l'optimisation" code trop rapidement.Suffit d'utiliser java.util.Objets.hash(Objet de valeurs...).
Objets.de hachage fait des appels Les tableaux de.hashCode(l'Objet a[])
Objects.hash(3.0f, -1.0f) === Objects.hash(-3.0f, 1.0f)
(via stackoverflow.com/questions/36848151/...)Je sais que c'est ok pour les non-égalité objets ont le même hashcodes. Cependant, le plus de collisions, le pire de la performance (par exemple, dans une table de hachage).
Autant que je sache, le meilleur de la cartographie de Z2 → Z est le "élégant, la fonction d'appariement" (google). Ici est la mise en œuvre
Cela va commencer à se chevauchent dès que vous obtenez la multiplication de débordement. Si la valeur absolue de x et y est inférieur à environ 46000, alors cela aura zéro collisions de hachage.
Il est souvent utile d'envisager Apache Commons HashCodeBuilder
et je recommande de regarder le référencés livre Efficace Java.
Il y a une stratégie commune de la génération d'un hashcode opération. Dans votre cas, ce serait :
}
Vous pouvez prendre un coup d'oeil à Google Goyave est Objets.hashCode(Objet...) méthode.
Cette question est assez vieux, mais je pense que l'idée va être effective tant que java existent. Laissez-nous analyser les approches ci-dessus:
Objects.hashCode(...)
est fluide et clair ce qui doit être fait, MAIS il utilise varargs (implicitement la création d'un tableau) et de plus, il implicitement boîtes chaque primitive, étant passé dans la méthode.x * 31 + y
est performance efficace: il n'y a pas de boxe, aucune condition explicite ou implicite de la création de la matrice des opérations utilisées. MAIS, il est pas clair ce qui doit être fait. Pourquoi le 31, pas Quarante deux? Pour ceux qui sont familiers avec la façon de hachage fonctionne il n'y a pas de difficultés à comprendre ce code, mais que pour les autres? Le deuxième écueil est qu'il est difficile d'étendre: vous pouvez facilement oublier d'ajouter de nouvelles valeurs dans le code de hachage si vous, par exemple, a voulu aller à la 3D et a ajouté z coordonner, car il vous oblige à copier-coller presque identique plusieurs fois.Je peux introduire la troisième approche, n'étant pas mentionné dans les réponses ci-dessus:
Il utilise un tableau temporaire pour contenir les entiers sont hachés, et appelant Les tableaux de.hashCode(), qui est disponible depuis Java 1.5, il y a aussi des versions pour d'autres types de primitives.
Pros: Il est SEC, fluide et complètement clairement ce qui doit être fait. Il ne souffre pas de l'implicite de la boxe et n'utilise implicite vararg. Il est relativement rapide et bon marché. Il peut être facilement étendu par l'ajout de numéros dans le tableau de l'initialiseur.
Contre: Il n'est pas aussi rapide que de copier-coller. Veuillez tenir compte que si le code de hachage est fréquemment appelé.
Meilleures salutations.
essayez d'ajouter leur hashcodes. ?
de retour de new Integer(x).hashCode()+new Integer(y).hashCode();
int
c'est l'emballage. Il serait plus simple d'utiliserx + y
.new Integer(int)
explicitement, utilisezInteger.valueOf(int)
à la place. Il y a un peu d'optimisation appelé integer mise en cache pour vous aider à augmenter les performances parfois. Il y a aussi une méthodeObjects.hashCode(Object)
, vous pouvez facilement passer votreint
, et il sera encadré dansInteger
automatiquement! Des acclamations.