Maison > Périphériques technologiques > Industrie informatique > Comment implémenter correctement le code de hashsh de Java

Comment implémenter correctement le code de hashsh de Java

尊渡假赌尊渡假赌尊渡假赌
Libérer: 2025-02-18 10:46:14
original
667 Les gens l'ont consulté

SitePoint Explore le monde Java: invitez les développeurs Java à contribuer

How to Implement Java's hashCode Correctly

SitePoint continue d'étendre son champ de contenu et se concentrera sur Java dans un avenir proche. Si vous êtes un développeur Java expérimenté et que vous souhaitez contribuer à notre contenu Java, veuillez nous contacter pour partager les idées de sujet que vous souhaitez écrire.

Implémentation correcte des méthodes equals et hashCode dans Java

Vous avez implémenté la méthode equals pour votre classe? super! Mais vous devez également implémenter la méthode . Comprenons pourquoi et comment l'implémenter correctement. hashCode Points clés:

Dans Java, les objets égaux devraient avoir le même code de hachage. Par conséquent, si la méthode
    est réécrite, une implémentation correspondante
  • doit être créée pour garantir la précision et la cohérence du stockage et de la récupération d'objets dans une collection basée sur le hachage. equals Lors de la mise en œuvre de hashCode, les mêmes champs utilisés dans la méthode
  • doivent être utilisés. Essayez d'éviter d'utiliser des champs et des collections mutables, car cela peut entraîner des problèmes de performance.
  • Les codes de hachage hashCode sont liés à l'optimisation des performances, vous ne devez donc pas consacrer trop d'efforts au hachage, à moins que l'analyse des performances n'indique des améliorations nécessaires. equals
  • Les collisions de hachage (deux objets différents ont le même code de hachage) peuvent être réduits en améliorant l'algorithme de hachage et en utilisant des nombres premiers plus grands comme multiplicateurs. Cela permet de distribuer plus uniformément les codes de hachage de l'ensemble, réduisant la possibilité de conflits de hachage et garantissant une récupération des données plus rapide.
  • et
Méthodes

equals Bien que la méthode hashCode soit raisonnable dans une perspective générale, la méthode

est plus technique. À strictement parler, ce n'est qu'un détail de mise en œuvre pour améliorer les performances.

equals La plupart des structures de données utilisent la méthode hashCode pour vérifier si elles contiennent un élément. Par exemple:

equals La variable

est vraie, car bien que les instances de "B" ne soient pas les mêmes (ignorez à nouveau la résidence de chaîne), elles sont égales.
List<String> list = Arrays.asList("a", "b", "c");
boolean contains = list.contains("b");
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cependant, la comparaison de chaque élément avec une instance transmise à la méthode contains est inefficace, tandis qu'une classe de structures de données utilise une méthode plus efficace. Au lieu de comparer les instances demandées avec chaque élément qu'ils contiennent, ils utilisent des raccourcis pour réduire le nombre d'instances qui peuvent être égales, puis comparer uniquement les instances.

Ce raccourci est le code de hachage, qui peut être considéré comme l'égalité de l'objet à réduire à une valeur entière. Les instances avec le même code de hachage ne sont pas nécessairement égales, mais les instances égales ont le même code de hachage. (Ou devrait avoir le même code de hachage, dont nous discuterons plus tard.) Ces structures de données sont généralement nommées d'après leur nom technique, qui contient "hachage" dans lequel contains est le représentant le plus célèbre.

Ils fonctionnent généralement comme suit: HashMap

  • Lors de l'ajout d'un élément, son code de hachage est utilisé pour calculer l'index dans le tableau interne (appelé seau).
  • Si d'autres éléments inégaux ont le même code de hachage, ils se retrouvent dans le même seau et doivent être regroupés, par exemple en les ajoutant à une liste.
  • Lors du passage d'une instance à la méthode contains, le seau est calculé à l'aide de son code de hachage. Seuls les éléments qu'il contient sont comparés à l'instance.

De cette manière, la mise en œuvre de la méthode contains peut nécessiter que très peu, idéalement sans comparaison equals.

Comme la méthode equals, la méthode hashCode est également définie dans la classe Object.

penser au hachage

Si la méthode hashCode est utilisée comme un raccourci pour déterminer l'égalité, alors il n'y a qu'une seule chose dont nous devrions vraiment nous soucier: les objets égaux devraient avoir le même code de hachage.

C'est aussi pourquoi si nous réécrivons la méthode equals, nous devons créer une implémentation correspondante hashCode! Sinon, les choses qui sont égales en fonction de notre implémentation peuvent ne pas avoir le même code de hachage, car ils utilisent l'implémentation de la classe Object.

hashCode Contrat de la méthode

Citer le code source:

hashCode L'accord général de la méthode est:

  • Chaque fois qu'il est appelé le même objet plusieurs fois lors de l'exécution d'une application Java, la méthode hashCode doit toujours renvoyer le même entier, à condition que les informations utilisées dans la comparaison equals de l'objet ne soient pas modifiées. Cet entier n'a pas besoin d'être cohérent entre l'exécution d'une application et l'autre exécution de la même application.
  • Si deux objets sont égaux selon la méthode equals(Object), l'appel à la méthode hashCode doit produire le même résultat entier sur chacun des deux objets.
  • Si les deux objets ne sont pas égaux selon la méthode equals(Object), vous n'avez pas besoin d'appeler la méthode hashCode sur les deux objets qui doivent produire des résultats entiers différents. Cependant, les programmeurs doivent se rendre compte que la génération de différents résultats entiers pour des objets inégaux peut améliorer les performances de la table de hachage.

Le premier point reflète l'attribut de cohérence de la méthode equals, et le deuxième point est les exigences que nous avons dessinées ci-dessus. Le troisième point illustre un détail important dont nous discuterons plus tard.

implément hashCode Méthode

Une implémentation très simple Person.hashCode est la suivante:

List<String> list = Arrays.asList("a", "b", "c");
boolean contains = list.contains("b");
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Le code de hachage humain est calculé en calculant les codes de hachage des champs connexes et en les combinant ensemble. Les deux sont laissés à la fonction utilitaire Objects pour le traitement. hash

Sélectionner le champ

Mais quels champs sont liés? Ces exigences aident à répondre à cette question: si un objet égal doit avoir le même code de hachage, le calcul du code de hachage ne doit contenir aucun champ qui n'est pas utilisé pour les vérifications d'égalité. (Sinon, seuls deux objets différents sur ces champs seront égaux, mais ont des codes de hachage différents.)

Par conséquent, l'ensemble des champs utilisés pour le hachage devrait être un sous-ensemble de l'ensemble des champs utilisés pour l'égalité. Par défaut, les deux utiliseront les mêmes champs, mais il y a quelques détails à considérer.

cohérence

Tout d'abord, il existe des exigences de cohérence. Il doit être interprété assez strictement. Bien qu'il permette au code de hachage de changer lorsque certains champs changent (ce qui est souvent inévitable pour les classes mutables), la structure de données de hachage n'est pas prête pour ce scénario.

Comme nous l'avons vu ci-dessus, le code de hachage est utilisé pour déterminer le seau de l'élément. Cependant, si les champs liés au hachage changent, le hachage n'est pas recalculé et le réseau interne n'est pas mis à jour.

Cela signifie que les requêtes ultérieures utilisant des objets égaux ou même en utilisant exactement la même instance échoueront! La structure de données calcule le code de hachage actuel (contrairement au code de hachage utilisé pour stocker les instances) et le recherche dans le mauvais seau.

Conclusion: il est préférable de ne pas utiliser de champs variables pour le calcul du code de hachage!

Performance

Le nombre de fois où le code de hachage est calculé peut être approximativement le même que le nombre de fois que la méthode

est appelée. Cela est susceptible de se produire dans la partie de performance critique du code, il est donc logique de considérer les performances. Et contrairement à la méthode equals, il y a plus de place pour l'optimisation ici. equals

à moins que des algorithmes complexes ne soient utilisés ou que de nombreux champs soient impliqués, le coût arithmétique de la combinaison de son code de hachage est aussi trivial que le coût inévitable. Mais déterminez si tous les champs doivent être inclus dans le calcul! En particulier, l'ensemble doit être sceptique. Par exemple, les listes et les collections calculeront la valeur de hachage pour chacun de leurs éléments. La question de savoir s'ils doivent être appelés devraient être pris en compte en fonction de la situation.

Si les performances sont essentielles, l'utilisation de

peut également être le meilleur choix, car il nécessite de créer un tableau pour ses paramètres mutables. Objects.hash

Mais la règle générale concernant l'optimisation s'applique toujours: n'optimisez pas trop tôt! En utilisant des algorithmes de code de hachage commun, peut-être l'abandon d'ensembles d'inclusion et d'optimisation ne se fait qu'après l'analyse des performances montre qu'il existe une possibilité d'amélioration.

conflit

Prenez tous vos efforts pour poursuivre les performances, alors qu'en est-il de cette implémentation?

List<String> list = Arrays.asList("a", "b", "c");
boolean contains = list.contains("b");
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Cela doit être rapide. Et les objets égaux auront le même code de hachage, nous allons donc bien à cet égard. En prime, aucun champ variable n'est impliqué!

Mais rappelez-vous ce que nous avions à propos des seaux avant? De cette façon, toutes les instances entreront le même seau! Cela se traduit généralement par une liste liée contenant tous les éléments, ce qui est très mauvais pour les performances. Par exemple, chaque

Call déclenche une analyse linéaire de la liste liée. contains

Par conséquent, nous voulons minimiser le nombre d'articles dans le même seau! Un algorithme qui renvoie un code de hachage qui est très différent même pour les objets très similaires est un bon début. Comment implémenter dépend en partie du champ sélectionné. Plus nous incluons dans le calcul, plus la possibilité que le code de hachage soit différente soit différente. Notez que c'est exactement l'opposé de ce que nous pensons de la performance. Donc, il est intéressant de noter que l'utilisation trop de ou trop peu de champs peuvent entraîner de mauvaises performances.

Une autre partie de la prévention des conflits est l'algorithme utilisé pour calculer réellement le hachage.

Calculer la valeur de hachage

Le moyen le plus simple de calculer le code de hachage de champ est d'appeler la méthode

. Ils peuvent être combinés manuellement. Un algorithme commun consiste à commencer par un nombre arbitraire, puis à le multiplier à plusieurs reprises par un autre nombre (généralement un petit nombre premier), puis à ajouter le hachage du champ: hashCode

List<String> list = Arrays.asList("a", "b", "c");
boolean contains = list.contains("b");
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Cela peut provoquer un débordement, mais cela ne provoque pas d'exceptions en Java, il n'y a donc pas de gros problème.

Notez que même d'excellents algorithmes de hachage peuvent entraîner des conflits inhabituellement fréquents si les données d'entrée ont un modèle spécifique. À titre d'exemple simple, supposons que nous calculons la valeur de hachage d'un point en ajoutant les coordonnées x et y du point. Cela semble assez bon jusqu'à ce que nous réalisions que nous traitons souvent des points sur la ligne droite f (x) = -x, ce qui signifie que pour tous ces points, x y == 0. Conflit, beaucoup!

Mais encore une fois: utilisez des algorithmes communs et ne vous inquiétez pas à moins que l'analyse des performances ne montre des problèmes.

Résumé

Nous avons vu que le calcul des codes de hachage est comme la compression de l'égalité en valeurs entières: les objets égaux doivent avoir le même code de hachage, et pour des raisons de performance, il est préférable de partager la même chose que peu d'objets inégaux que possible que possible avec le même hachage code.

Cela signifie que si la méthode

est réécrite, la méthode equals doit toujours être réécrite. hashCode

Implémentez

Méthode: hashCode

    Utilisez les mêmes champs (ou sous-ensembles de ceux-ci) que celui utilisé dans la méthode
  • . equals
  • Il est préférable de ne pas inclure des champs variables.
  • Envisagez de ne pas appeler la méthode
  • sur la collection. hashCode
  • Utilisez des algorithmes communs à moins que le modèle de données d'entrée soit le contraire.
N'oubliez pas que la méthode

est liée aux performances, alors ne gaspillez pas trop d'énergie à moins que l'analyse des performances ne montre qu'elle est nécessaire. hashCode

FAQ sur la mise en œuvre correcte Java

Méthodes (FAQ) hashCode

Quelle est la signification de la méthode

en Java? hashCode()

La méthode

en Java est une fonction intégrée qui renvoie une valeur entière. Il est principalement utilisé pour les collections basées sur le hachage (telles que hashCode(), HashMap et HashSet) pour stocker et récupérer des objets plus efficacement. La méthode HashTable fonctionne en conjonction avec la méthode hashCode() pour s'assurer que chaque objet a un identifiant unique. Cela aide à récupérer rapidement les données, en particulier dans les grandes collections, améliorant ainsi les performances des applications Java. equals()

Comment fonctionne la méthode hashCode() en Java?

La méthode hashCode() dans Java fonctionne en générant une valeur entière qui représente l'adresse mémoire de l'objet. Cette valeur est utilisée comme numéro d'index de l'objet dans une collection basée sur le hachage. Lorsque vous appelez la méthode hashCode() sur l'objet, il utilise un algorithme de hachage pour générer cet entier unique. Cependant, il est important de noter que deux objets différents peuvent avoir le même hashCode, qui est appelé conflit de hachage.

Quelle est la convention entre les méthodes

et equals() dans hashCode() en java?

La convention entre

et equals() méthodes dans hashCode() en Java est un ensemble de règles utilisées pour gérer leurs interactions. La convention indique que si deux objets sont égaux selon la méthode equals(), l'appel à la méthode hashCode() doit produire le même résultat entier sur chacun des deux objets. Cela garantit la cohérence et la précision lors du stockage et de la récupération d'objets dans une collection basée sur le hachage.

Comment réécrire la méthode hashCode() en Java?

Réécrivez la méthode hashCode() dans Java inclut la fourniture de votre propre implémentation qui renvoie un entier unique pour chaque objet. Cela peut être réalisé en utilisant des variables d'instance de l'objet et du multiplicateur privilégié. Les nombres premiers aident à distribuer uniformément les codes de hachage de l'ensemble, réduisant ainsi la possibilité de collisions de hachage.

Qu'est-ce que le conflit de hachage et comment l'éviter?

Le conflit de hachage

signifie que la méthode hashCode() génère le même entier pour deux objets différents. S'il n'est pas géré correctement, cela peut entraîner une perte de données. Pour éviter les conflits de hachage, vous pouvez améliorer l'algorithme de hachage pour générer des entiers plus uniques. De plus, l'utilisation de nombres premiers plus importants comme multiplicateurs peut aider à distribuer plus uniformément les codes de hachage de l'ensemble.

Pourquoi la méthode hashCode() devrait-elle être réécrite?

Réécrivez les méthodes hashCode() peut améliorer les performances des applications Java, en particulier lorsqu'ils traitent de grandes collections. En fournissant votre propre implémentation, vous pouvez générer des codes de hachage plus uniques et uniformément distribués, réduisant la possibilité de conflits de hachage et garantissant une récupération des données plus rapide.

En Java, deux objets inégaux peuvent-ils avoir le même hashCode?

Oui, en Java, deux objets inégaux peuvent avoir le même hashCode. C'est ce qu'on appelle le conflit de hachage. Cependant, en améliorant l'algorithme de hachage et en utilisant un plus grand nombre de premiers multiplicateurs, la possibilité que cela se produise peut être réduite.

Que se passe-t-il si je ne réécrit pas la méthode hashCode()?

Si vous ne remplacez pas la méthode hashCode(), Java utilisera son implémentation par défaut, qui peut ne pas fournir de code de hachage unique pour chaque objet. Cela peut entraîner des conflits de hachage et une récupération des données plus lente dans les collections basées sur le hachage.

hashCode() Comment améliorer les performances des applications Java?

La méthode

hashCode() améliore les performances d'une application Java en fournissant un identifiant unique pour chaque objet. Cela permet de récupérer les données plus rapidement dans les collections basées sur le hachage, car l'objet peut être trouvé directement en utilisant le code de hachage de l'objet sans rechercher toute la collection.

Puis-je utiliser la méthode hashCode() dans une collection non basée sur des hash?

Bien que la méthode hashCode() soit principalement utilisée pour les collections basées sur le hachage, elle peut également être utilisée pour les collections non basées sur Hash. Cependant, les avantages peuvent être moins évidents, car les collections non basées sur les Hash ne reposent pas sur le code de hachage pour le stockage et la récupération des données.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal