ProgrammationDéveloppeur Java

Comment fonctionne le mécanisme de redéfinition de la méthode hashCode() en Java, quelles règles doivent être respectées, et à quels bogues critiques peut conduire la violation de ces règles ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

La redéfinition de la méthode hashCode() est étroitement liée à la redéfinition de equals() : les deux méthodes forment la base pour une utilisation correcte de l'objet dans des collections telles que HashMap, HashSet, Hashtable et d'autres structures basées sur la comparaison et les fonctions de hachage.

Règles :

  • Si vous redéfinissez equals(), vous devez également redéfinir hashCode().
  • Les objets égaux par equals() doivent retourner le même hashCode().
  • Il est recommandé d'utiliser des méthodes standard pour générer le hachage, comme Objects.hash() ou des modèles d'IDE, pour éviter les erreurs.
  • hashCode() doit retourner la même valeur pour un même objet tout au long de sa "vie" (si les champs impliqués dans hashCode sont immuables).
class User { private String name; public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof User)) return false; User user = (User) o; return Objects.equals(name, user.name); } public int hashCode() { return Objects.hash(name); } }

Question piège.

Question : "Que se passe-t-il si deux objets différents par equals() retournent le même hashCode() ? Est-ce une erreur ?"

Réponse : Non, ce n'est pas une erreur. Les collisions de hachage sont résolubles et attendues - il est juste important que si les objets sont égaux par equals, leur hashCode soit identique. Si des objets différents par equals donnent le même hashCode, les collections fonctionneront plus lentement (à cause du plus grand nombre de collisions), mais fonctionneront correctement.

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet.


Histoire

Dans un logiciel financier, des projets étaient comparés sur plusieurs champs, mais seule la méthode equals() avait été redéfinie. Les objets étaient stockés dans un HashSet, des doublons apparaissaient car hashCode() n'était pas redéfini et fonctionnait par défaut (différait pour chaque instance).


Histoire

Dans un système de gestion d'entrepôt, après des modifications de la logique métier, equals() a été étendu, mais hashCode() n'a pas été mis à jour. Des objets avec des hashCode différents, mais equals=true, se perdaient dans HashMap (ne pouvaient pas être trouvés par clé), entraînant de grandes erreurs financières.


Histoire

Dans une application web, des champs modifiables étaient utilisés dans le calcul du hashCode. Lors de la mise à jour d'une valeur de champ interne, le hachage changeait et l'objet "se perdait" pour HashSet/HashMap : il était impossible de le trouver ou de le supprimer par les méthodes standard, ce qui entraînait des fuites de mémoire et des bogues.