J'ai quelques difficultés à écrire une méthode hashCode()
pour une classe que j'ai créée. Cette classe est destinée à être utilisée dans un TreeSet et implémente donc Comparable. La classe a les variables suivantes:
public class Node implements Comparable<Node> {
Matrix matrix;
int[] coordinates= new int[2];
Node father;
int depth;
int cost;
Voici l'implémentation de la méthode compareTo()
. Je veux que la TreeSet
organise ces structures de nœud en fonction de leur coût. Par conséquent, compareTo()
renvoie le résultat d'une simple soustraction.
public int compareTo(Node nodeToCompare) {
return this.cost - nodeToCompare.cost;
}
J'ai également implémenté une méthode equals()
.
public boolean equals(Object objectToCompare) {
if(objectToCompare== this) {return true;}
if(objectToCompare== null || objectToCompare.getClass()!= this.getClass()) {return false;}
Node objectNode= (Node) objectToCompare;
return this.father.equals(objectNode.father) &&
this.depth== objectNode.depth &&
this.cost== objectNode.cost &&
this.matrix.equals(objectNode.matrix) &&
Arrays.equals(this.coordinates, objectNode.coordinates);
}
Cela dit, j'ai quelques questions à poser:
equals()
, dois-je implémenter une nouvelle méthode hashCode()
?method()
avec ces variables? (Notez que la variable matrice du type Matrix a une méthode hashCode()
implémentée)C'est tout!
Votre méthode compareTo
n'est pas compatible avec votre méthode equals
: votre méthode compareTo
indique que deux instances sont équivalentes si elles ont le même cost
- de sorte qu'un TreeSet
ne peut jamais contenir au plus une instance avec un cost
donné - mais votre méthode equals
ne peut jamais contenir qu'au plus ils ne sont équivalents que s'ils ont la même cost
et sont les mêmes de diverses manières.
Donc, en supposant que votre méthode equals
soit correcte:
compareTo
pour être cohérent avec elle.hashCode
qui lui soit cohérente. Je recommande d'utiliser le même type de logique que celui utilisé par Java.util.List.hashCode()
, qui est un moyen simple et efficace d'assembler les codes de hachage des objets composants dans un ordre spécifique; fondamentalement, vous écririez quelque chose comme: int hashCode = 1; hashCode = 31 * hashCode + (père == null? 0: father.hashCode ()); hashCode = 31 * hashCode + profondeur; hashCode = 31 * hashCode + cost; HashCode = 31 * hashCode + matrix.hashCode (); HashCode = 31 * hashCode + Java.util.Arrays.hashCode (coordonnées); retourne hashCode;
Intellij IDEA peut le faire en tant que fonction "clic droit". Le fait de le faire correctement vous en apprendra beaucoup.
Et vous devriez outrepasser les deux dans tous les cas.
Le contrat pour la méthode hashCode stipule que si deux objets sont égaux, l'appel de hashCode () devrait vous donner le même résultat entier. L’inverse ne doit pas nécessairement être vrai, c’est-à-dire que si deux hashCodes sont identiques, les objets ne doivent pas s’égaler.
En examinant votre méthode equals (qui nécessite une traduction de variable btw), vous pouvez ajouter les hashCodes de toutes les variables de membre interne devant être égales pour que votre méthode equals donne true. par exemple.
public int hashCode() {
return this.matrix.hashCode() +
this.coordinates[0] +
this.coordinates[1] +
this.father.hashCode() +
this.depth + this.cost;
}
Ce qui précède suppose que la matrice et le père ne sont jamais nuls, vous devez vous assurer de vérifier les nuls si ce n'est pas le cas.
Si vous vous sentez plus aventureux, vous pouvez multiplier quelques-uns de ce qui précède par un nombre premier pour éviter les collisions hashCode avec différentes données (cela vous aidera à améliorer les performances si vous utilisez votre classe dans hashTables et hashMaps). Si vous devez prendre en charge les valeurs NULL, la méthode ci-dessus peut être écrite un peu mieux comme ceci:
public int hashCode() {
return ((this.matrix == null) ? 0 : this.matrix.hashCode()) +
17 * this.coordinates[0] +
this.coordinates[1] +
((this.father == null) ? 0 : this.father.hashCode()) +
31 * this.depth + 19 * this.cost;
}
Si votre collection est petite, vous pouvez renvoyer une constante de la méthode hashCode. Il utilise pour trouver rapidement. hashCodes est comme les boîtes, qui conservent des éléments. Les règles sont:
Ensuite, vous retournez constant, vous obéissez à ces 2 règles, mais cela peut réduire considérablement les performances sur les petites listes (car JVM recherchera dans tous les éléments, et pas uniquement dans la même boîte). Mais le retour constant est la mauvaise approche.
PS: Désolé pour mon écriture. L'anglais n'est pas ma langue maternelle.
PPS: normalement, vous devez implémenter la méthode hashCode de la même manière qu'égal (utilise les mêmes éléments)