Vous avez sans doute déjà surcharger equals(Object o) ou hashCode() et réaliser compareTo(Object o) de l’interface Comparable. Mais saviez-vous qu’il existe un lien entre ces trois méthodes tout comme chacune d’elle doit avoir un comportement bien défini.
Ainsi en regardant l’API on peux lire ceci pour equals
“Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.“
et pour hashCode on trouve ceci
“ - If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
- It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.“
Et enfin, pour la méthode compareTo
“ It is strongly recommended, but not strictly required that (x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any class that implements the Comparable interface and violates this condition should clearly indicate this fact. The recommended language is “Note: this class has a natural ordering that is inconsistent with equals.” “
En résumé, pour une classe qui implémente compareTo et surcharge equals et hashcode.
- Si o1.compareTo(o2) retourne 0 alors o1.equals(o2) doit retourne true et cela doit-être vrai également pour o2.compareTo(o1) et o2.equals(o1).
- Si o1.equals(o2) alors o1.hashCode()==o2.hashCode()
- Et donc o1.compareTo(o2)==0 si o1.hashCode()==o2.hashCode()
On pourrais donc-être tenté d’écrire
public int hashCode() {
int coef = 3;
hash += coef*propriete.hashCode();
return hash;
}
public boolean equals(Object o) {
if (o == null )
return false;
return this.hashCode()==o.hashCode();
}
public int compareTo(Object o) {
if ( this.equals(o) )
return 0;
// Reste de comparaison
}
Mais cela est loin d’être parfait car tout au long de l’exécution de votre application hashCode doit toujours renvoyer la même valeur quelque soit le contenu de l’objet alors que equals et compareTo doivent-prendre en compte le contenu variable de votre objet.
Et vous, comment surchargez-vous ces méthodes de comparaison ?





Bonjour,
je ne suis pas d’accord avec ton dernier paragraphe.
Le hashCode d’un objet ne doit pas varier uniquement si les éléments utilisés dans le equals n’ont pas changé.
Comme le dit la javadoc :
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.
Si tu créés une classe Personne avec nom, prénom et age, le changement d’une des trois valeurs sur une instance de cette classe change la valeur du hashcode de cette instance.
@Jollivet Christophe : Moi je n’avais pas vu ça comme ça. Pour toi hashCode et equals sont toujours en égalité alors ?
dans Java Efficace (de Joshua Bloch), il s’agit de la recommandation n°8 : Toujours redéfinir hashCode lorsque equals est redéfini.
- deux objets égaux doivent avoir la même valeur de hashCode
- par contre deux objets de même valeur de hashCode ne sont pas forcément égaux
Ca me revient à l’esprit que lors de l’examen SCJP, il y avait plusieurs questions sur ce sujet. Et en effet, on y disait bien que deux objets qui sont égaux ont le même résultat avec hashcode mais que deux objets qui ont le même hashcode ne sont pas nécessairement égaux.
Bon très bien je m’incline. Mais il reste une chose qui ne me parrait pas très claire :
Si equals et hashCode doivent avaoir un comportement lié (deux hascode égaux donc equals vaut true), dans quels cas pourrions nous avoir un hashcode égal mais un equals faux ?
Attention
“deux objets qui ont le même hashcode ne sont pas nécessairement égaux”
Donc quand tu dis: “deux hascode égaux donc equals vaut true” ce n’est pas bon.
Le but du hashcode est de permettre un meilleur “hashage” lors d’une recherche.
@Alexis : Le but du hashcode est de permettre un meilleur hashage oui mais son comportement doit malgré tout être lié avec celui de equals.
Dans certains cas on peut même fixer hashcode à une constante. Pourtant les objets ne sont aps égaux. J’ai dû le faire il y a peu avec un objet métier copmpliqué qui n’avait jamais rien de constant, qui avait des règles de comparaisons très compliquées, qui obligeaient à cette extrémité. equals était bien redéfini mais hashcode valait une const. Oui c’est bizarre, mais on s’y fait.