À propos de Hashcode, dans Wikipedia:
Dans le langage de programmation Java, chaque classe fournit implicitement ou explicitement une méthode HashCode (), qui digère les données stockées dans une instance de la classe en une seule valeur de hachage (un entier signé 32 bits).
HashCode extrait un entier 32 bits basé sur toutes les données stockées dans une instance d'objet. Le but de cet entier est d'indiquer l'unicité de l'instance. Il est quelque peu similaire au code MD5, et chaque fichier peut générer un code MD5 unique via l'algorithme MD5. Cependant, le HashCode dans Java n'implémente pas vraiment le HashCode pour générer un HashCode unique pour chaque objet, et il y a encore une certaine chance de duplication.
Jetons un coup d'œil à la classe d'objets en premier. Nous savons que la classe d'objets est la classe parent directe ou indirecte de toutes les classes d'un programme Java et est au point le plus élevé du niveau de classe. De nombreuses méthodes courantes sont définies dans la classe d'objets, y compris la méthode HashCode dont nous voulons parler, comme suit
Classe native finale publique <?> getClass (); public native int hashcode (); public booléen est égal (objet obj) {return (this == obj); } public String toString () {return getClass (). getName () + "@" + integer.tohexString (hashcode ()); }Notez qu'il existe un modificateur natif devant la méthode HashCode, ce qui signifie que la méthode HashCode est implémentée dans une langue non java. La méthode spécifique est implémentée en externe et renvoie l'adresse de l'objet mémoire.
Dans de nombreuses classes Java, les méthodes égales et HashCode sont réécrites. Pourquoi est-ce? La classe de chaîne la plus courante, comme si je définis deux chaînes avec les mêmes caractères, alors lors de la comparaison, le résultat que je veux devrait être égal. Si vous ne remplacez pas les méthodes Equals et HashCode, elles ne seront certainement pas égales, car les adresses mémoire des deux objets sont différentes.
public int hashcode () {int h = hash; if (h == 0) {int off = offset; char Val [] = valeur; int len = count; pour (int i = 0; i <len; i ++) {h = 31 * h + val [off ++]; } hash = h; } return h; }En fait, ce code est la mise en œuvre de cette expression mathématique
s [0] * 31 ^ (n-1) + s [1] * 31 ^ (n-2) +… + s [n-1]
S [i] est le i-tème caractère d'une chaîne, et n est la longueur d'une chaîne. Alors pourquoi utiliser 31 ici au lieu d'autres chiffres? Java efficace dit ceci: la raison pour laquelle 31 est choisi est parce que c'est un nombre de premiers. Si le multiplicateur est un nombre pair et que la multiplication déborde, les informations seront perdues, car la multiplication avec 2 est équivalente au fonctionnement de décalage. Les avantages de l'utilisation de nombres premiers ne sont pas évidents, mais les résultats du hachage sont conventionnellement utilisés pour calculer les résultats du hachage. 31 a une bonne fonctionnalité, qui consiste à utiliser le décalage et la soustraction au lieu de la multiplication pour obtenir de meilleures performances: 31 * i == (i << 5) -I. Les machines virtuelles peuvent effectuer automatiquement cette optimisation.
Comme vous pouvez le voir, la classe de chaîne utilise sa valeur de valeur comme paramètre pour calculer HashCode, c'est-à-dire que la même valeur aura certainement la même valeur de code de hash. Ceci est également facile à comprendre, car les valeurs de valeur sont les mêmes, donc si la comparaison égale est également égale, la méthode égale est égale, alors le code de hash doit être égal. L'inverse n'est pas nécessairement vrai. Il ne garantit pas que le même code de hachage doit avoir le même objet.
Une bonne fonction de hachage devrait ressembler à ceci: produire des codes de hashs inégaux pour différents objets.
Dans les cas idéaux, la fonction de hachage doit distribuer uniformément des instances inégales dans l'ensemble sur tous les codes de hash possible. Il est très difficile d'atteindre cette situation idéale, au moins Java ne l'a pas atteinte. Parce que nous pouvons voir que HashCode est généré de manière non aléatoire, et il a certaines règles, qui est l'équation mathématique ci-dessus. Nous pouvons construire certains qui ont le même code de hash mais différentes valeurs de valeur, par exemple: le code de hash de AA et BB est le même.
Le code suivant:
classe publique Main {public static void main (String [] args) {main m = new Main (); System.out.println (M); System.out.println (Integer.tohexString (M.HashCode ())); String a = "aa"; String b = "bb"; System.out.println (a.hashcode ()); System.out.println (B.HashCode ()); }}Résultat de sortie:
Main @ 2A139A55 2A139A55 2112 2112
Généralement, lors de la réécriture de la fonction égale, vous devez également réécrire la fonction HashCode. Pourquoi est-ce?
Jetons un coup d'œil à cet exemple, créons un employé de classe simple
Employé de classe publique {ID entier privé; String privé FirstName; String privé LastName; Département de cordes privées; public Integer getID () {return id; } public void setid (INGER ID) {this.id = id; } public String getFirstName () {return firstName; } public void setFirstName (String FirstName) {this.firstName = FirstName; } public String getLastName () {return lastName; } public void setLastName (String LastName) {this.lastName = LastName; } public String getDepartment () {return département; } public void setDepartment (string Department) {this.department = département; }}La classe des employés ci-dessus n'a que des propriétés et des getters et des setters très basiques. Considérez maintenant une situation où vous devez comparer deux employés.
classe publique EqualSTest {public static void main (String [] args) {Employee e1 = nouvel employé (); Employé E2 = nouvel employé (); e1.setid (100); e2.setid (100); // imprime false dans console System.out.println (e1.equals (e2)); }}Il ne fait aucun doute que le programme ci-dessus sortira faux, mais en fait, les deux objets ci-dessus représentent par le biais d'un employé. La vraie logique commerciale espère que nous retournerons vrai.
Pour y parvenir, nous devons réécrire la méthode égale.
public booléen est égal (objet o) {if (o == null) {return false; } if (o == this) {return true; } if (getClass ()! = o.getClass ()) {return false; } Employé e = (employé) o; return (this.getId () == e.getId ());} Ajoutez cette méthode à la classe ci-dessus et Eauqlstest sortira True.
Alors avons-nous fini? Non, changeons la méthode de test et jetons un coup d'œil.
Importer java.util.hashset; import java.util.set; classe publique Equalstest {public static void main (String [] args) {employee e1 = nouvel employé (); employee e2 = nouvel employé (); e1.setid (100); e2.setid (100); // imprimés 'system. New Hashset <Lesyee> (); Employés.Add (E1); Employés.Add (E2); // imprime deux objets Ssystem.out.println (Employés);}Le programme ci-dessus produit deux résultats. Si les deux objets d'employé sont égaux à renvoyer True, un seul objet doit être stocké dans l'ensemble. Quel est le problème?
Nous avons oublié la deuxième méthode importante HashCode (). Tout comme Javadoc de JDK l'a dit, si vous réécrivez la méthode equals (), vous devez réécrire la méthode hashcode (). Ajoutons la méthode suivante et le programme s'exécutera correctement.
@Override public int hashcode () {final int prime = 31; Int résultat = 1; result = prime * result + getID (); Résultat de retour; }Choses à retenir
Essayez de vous assurer que la même propriété de l'objet est utilisée pour générer deux méthodes: HashCode () et Equals (). Dans notre cas, nous utilisons les ID des employés.
La méthode Eqauls doit être cohérente (si l'objet n'est pas modifié, les égaux doivent renvoyer la même valeur)
À tout moment tant que A.equals (b), a.hashcode () doit être égal à B.Hashcode ().
Les deux doivent être réécrits en même temps.
Résumer
Ce qui précède est tout sur la compréhension approfondie de cet article de la méthode HashCode en Java, et j'espère qu'elle sera utile à tout le monde. Les amis intéressés peuvent continuer à se référer à d'autres sujets connexes sur ce site. S'il y a des lacunes, veuillez laisser un message pour le signaler. Merci vos amis pour votre soutien pour ce site!