Pourquoi hashCode() renvoient la même valeur pour les différents objets en Java?
Une citation du livre que je suis en train de lire La Tête La Première, Java:
Le point est que hashcodes peut être le même sans nécessairement garantir que les objets sont égaux, parce que l'algorithme de hachage utilisé dans le
hashCode()
méthode qui pourrait arriver à retourner la même valeur pour plusieurs objets.
Pourquoi le hashCode()
méthode de retourner la même valeur pour les différents objets? N'est-ce pas causer des problèmes?
Parce que par exemple le point de HashSet en avoir un seul des codes de hachage par élément. Et cela semble inutile si la paire d'objets peuvent avoir le même code de hachage.
Non, le point d'une valeur de hachage est de mapper chaque objet à un entier. Ensuite, vous pouvez les stocker dans un tableau en vertu de cette valeur (en fait, vous appliquez d'abord un int->int fonction de hachage à la carte à la plage du tableau). Si les deux hashCode() et la fonction de hachage sont rapides, vous bénéficiez d'un accès rapide à l'objet lorsque vous souhaitez récupérer à partir du tableau -- mais, sauf si vous savez tous les objets à l'avance, il peut toujours arriver que les deux objets de la carte de la même valeur. Que l'on appelle une collision, et à cause de collisions, vous ne comptez pas sur la fonction de hachage, mais également utiliser des "égaux" méthode de comparaison.
Merci, c'était très clair.
Content d'avoir pu aider. J'ai tapé une explication élaborée ci-dessous, pour l'enregistrement.
Non, le point d'une valeur de hachage est de mapper chaque objet à un entier. Ensuite, vous pouvez les stocker dans un tableau en vertu de cette valeur (en fait, vous appliquez d'abord un int->int fonction de hachage à la carte à la plage du tableau). Si les deux hashCode() et la fonction de hachage sont rapides, vous bénéficiez d'un accès rapide à l'objet lorsque vous souhaitez récupérer à partir du tableau -- mais, sauf si vous savez tous les objets à l'avance, il peut toujours arriver que les deux objets de la carte de la même valeur. Que l'on appelle une collision, et à cause de collisions, vous ne comptez pas sur la fonction de hachage, mais également utiliser des "égaux" méthode de comparaison.
Merci, c'était très clair.
Content d'avoir pu aider. J'ai tapé une explication élaborée ci-dessous, pour l'enregistrement.
OriginalL'auteur Eugene | 2010-12-05
Vous devez vous connecter pour publier un commentaire.
de hachage un objet signifie "de trouver une bonne valeur descriptive (nombre) qui peuvent être reproduites par la même instance, encore et encore". Parce que des codes de hachage à partir de Java
Object.hashCode()
sont de typeint
, vous ne pouvez avoir2^32
des valeurs différentes. C'est la raison pour laquelle vous avez soi-disant "collisions", selon l'algorithme de hachage, lorsque deux Objets distincts produire le même hashCode.Généralement, cela ne produit pas tous les problèmes, car
hashCode()
est principalement utilisé avecequals()
. Par exemple, unHashMap
appellerahashCode()
sur ses clés, à savoir si les touches peut-être déjà contenues dans la table de hachage. Si la table de hachage ne trouve pas le code de hachage, il est évident que la clé n'est pas contenue dans la table de hachage encore. Mais s'il le fait, il aura à vérifier toutes les clés ayant le même code de hachage à l'aide deequals()
.I. e.
Mais
Si
equals()
ethashCode()
sont mis en œuvre correctement.Pour une description plus précise de la générale
hashCode
contrat, voir la Javadoc.OriginalL'auteur Lukas Eder
Il y a seulement un peu plus de 4 milliards d'possible hashcodes (la plage d'un
int
) , mais le nombre d'objets vous pouvez choisir de créer est beaucoup plus grande. Par conséquent, certains objets doivent partager le même code de hachage, par le casier principe.Par exemple le nombre de chaînes contenant 10 lettres de A-Z est de 26**10, qui est 141167095653376. Il est impossible de céder l'ensemble de ces chaînes un unique code de hachage. Ni est-il important - le code de hachage n'a pas besoin d'être unique. Il faut juste ne pas avoir trop de collisions de données réelles.
OriginalL'auteur Mark Byers
L'idée d'une table de hachage est que vous voulez être en mesure de réaliser un discbased appelé dictionnaire de manière efficace. Un dictionnaire est un magasin de clé/valeur, c'est à dire, vous voulez être en mesure de stocker certains objets sous une certaine touche et, plus tard, être en mesure de récupérer à nouveau à l'aide de la même clé.
L'un des moyens les plus efficaces pour les valeurs de l'accès est de les stocker dans un tableau. Par exemple, nous avons pu réaliser un dictionnaire qui utilise des entiers pour les clés et les Chaînes de valeurs comme suit:
Malheureusement, cette approche n'est pas très général: l'index d'un tableau doit être une valeur entière, mais, idéalement, nous aimerions être en mesure d'utiliser arbitraire sortes d'objets pour nos clés, non seulement des nombres entiers.
Maintenant, la façon de résoudre ce point est d'avoir un moyen de la cartographie de l'arbitraire des objets de valeurs entières, à qui nous avons pu ensuite utiliser que des clés de notre tableau. En Java, c'est ce que
hashCode()
. Alors maintenant, nous pourrions essayer de mettre en œuvre une Chaîne de caractères->String dictionnaire:Mais hé, si il y a un objet qui nous aimerions utiliser comme une clé, mais son
hashCode
méthode renvoie une valeur qui est supérieure ou égale àDICT_SIZE
? Ensuite, nous aurions une ArrayIndexOutOfBoundsException et qui ne serait pas souhaitable. Donc, nous allons juste faire aussi grand que nous le pouvons, droite?Mais cela signifierait que nous aurions à allouer ginormeous quantités de mémoire pour notre tableau, même si nous avons l'intention de stocker quelques éléments. Donc ça ne peut pas être la meilleure solution, et en fait, nous pouvons faire mieux. Supposons que nous avions une fonction
h
que pour toutDICT_SIZE
cartes arbitraire entiers dans la gamme[0, DICT_SIZE[
. Alors nous pourrions l'appliquerh
quelle que soit lahashCode()
méthode d'un objet clé retourne et soyez certains que nous restons dans les limites de la sous-matrice.Que la fonction est appelée fonction de hachage. Maintenant, nous pouvons adapter notre dictionnaire en œuvre pour éviter la ArrayIndexOutOfBoundsException:
Mais qui introduit un autre problème: que faire si
h
cartes deux principaux indices de la même valeur? Par exemple:peut produire les mêmes valeurs pour
keyA
etkeyB
, et dans ce cas nous écraser accidentellement une valeur dans notre tableau:Bien, vous pouvez dire, ensuite, nous avons juste à nous assurer de mettre en œuvre
h
d'une manière telle que cela ne se produise jamais. Malheureusement, ce n'est pas possible en général. Considérons le code suivant:Cette boucle magasins
DICT_SIZE + 1
valeurs (toujours la même valeur, en fait, à savoir la Chaîne "dummy") dans le dictionnaire. Mhh, mais le tableau ne peut stocker que deDICT_SIZE
entrées différentes! Cela signifie que, lorsque nous utilisonsh
, nous écraser (au moins) une entrée. Ou en d'autres termes,h
mappe les deux clés différentes pour la même valeur! Ces "collisions" ne peut pas être évitée: si n pigeons essayer d'aller en n-1 pigeon trous, au moins deux d'entre eux ont d'aller dans le même trou.Mais ce que nous pouvons faire est d'étendre notre mise en œuvre, de sorte que l'ensemble peut stocker plusieurs valeurs sous le même index. Ceci peut être facilement fait en utilisant les listes. Ainsi, au lieu de l'aide:
nous écrire:
(Côté remarque: notez que Java n'autorise pas la création de tableaux de types génériques, de sorte que la ligne ci-dessus ne serait pas de compilation -- mais vous voyez l'idée).
Qui va changer l'accès au dictionnaire comme suit:
Dans le cas de notre hashfunction
h
renvoie des valeurs différentes pour l'ensemble de nos clés, cela va se traduire, dans une liste avec un seul élément de chaque, et de récupération des éléments est très simple:Mais nous savons déjà qu'en général
h
sera la carte de clés différentes pour le même entier, parfois. Dans ces cas, les listes contiendront plus d'une valeur. Pour la récupération, nous avons à parcourir toute la liste pour trouver la valeur "correct", mais comment aurions-nous la reconnaître?Bien, au lieu de stocker la valeur seul, on peut toujours stocker les complet (clé,valeur) paire dans les listes. Puis recherche serait effectuée en deux étapes:
Maintenant l'ajout et la récupération sont devenues tellement complexes qu'il n'est pas indécent de traiter nous-mêmes méthodes distinctes pour ces opérations:
Donc, pour que cette approche fonctionne, nous avons besoin de deux opérations de comparaison: la méthode hashCode pour trouver la liste dans le tableau (ce qui fonctionne rapidement si
hashCode()
eth
sont à la fois rapides) et unequals
méthode dont nous avons besoin, quand nous allons à travers la liste.C'est l'idée générale de hachage, et vous reconnaîtrez la
put
etget
méthode dejava.util.Map.
bien sûr, la mise en œuvre est une simplification excessive, mais il doit illustrer l'essentiel de tout cela.Naturellement, cette approche n'est pas limitée à des Chaînes, il fonctionne pour tous les types d'objets, depuis les méthodes
hashCode()
etequals
sont membres de haut niveau de la classe java.lang.Objet et toutes les autres classes héritent de cette.Comme vous pouvez le voir, il n'a pas vraiment d'importance si les deux objets distincts retourner la même valeur dans leur
hashCode()
méthode: l'approche ci-dessus fonctionnera toujours! Mais encore, il est souhaitable qu'ils retournent des valeurs différentes pour diminuer les risques de collisions de hachage produit parh
. Nous avons vu que celles-ci ne peuvent être évitées 100% en général, mais le moins de collisions, plus efficace notre table de hachage devient. Dans le pire des cas, toutes les clés de la carte pour le même index de tableau: dans ce cas, toutes les paires sont stockées dans une liste et de trouver une valeur qui deviendra alors une opération avec des coûts linéaire en la taille de la table de hachage.Eder: Votre réponse était non seulement de manière plus concise (et encore correcte et facile à comprendre), vous avez également eu moyen de plus de crédit que mon tl;dr réponse 😉
Il n'. Je vous ai donné de crédit pour l'effort 🙂
Aww... dommage de crédit! C'est gentil! 😉
Incroyable! 🙂 Marqué comme accepté un! Merci beaucoup encore une fois.
OriginalL'auteur Thomas
Le hashCode() valeur peut être utilisé pour trouver rapidement un objet en utilisant le code de hachage comme une adresse pour une table de hachage seau où il est stocké.
Si plusieurs objets renvoient la même valeur de hashCode(), cela signifie qu'elles devraient être stockées dans le même seau. Si plusieurs objets sont stockés dans le même seau, il signifie qu'en moyenne, il nécessite plusieurs opérations de comparaison pour rechercher un objet donné.
Au lieu d'utiliser equals() pour comparer deux objets pour voir si elles sont sémantiquement égalité.
OriginalL'auteur JLund
Que je comprends, le travail de la méthode hashcode est de créer des seaux pour le hachage des éléments, de Sorte que la récupération peut être plus rapide. Si chaque objet sera de retour même valeur, ce n'est pas de faire de hachage.
OriginalL'auteur Vishwanath
Je pense que c'est une assez inefficace algorithme de hachage pour 2 objets ont le même code de hachage.
Et comment est-ce que votre réponse invalide la mienne? C'est toujours inefficace juste plus pratique.
Si la avec un algorithme, la moyenne de l'élément dans un hachage de définir des actions d'un seau avec de 0,1 autres éléments, mais un peu plus cher algorithme pourrait éliminer toutes les collisions, le dernier algorithme ne serait plus efficace si son coût plus élevé était à moins d'un dixième du coût d'une comparaison supplémentaire. Si un algorithme de hachage prend beaucoup de temps, un manque total de collisions pourrait être un signe qu'un algorithme plus rapide pourrait être plus efficace.
Donc, de nombreux ifs dans ces 2 états...oui vous avez raison, mais vous allez à des moyens extrêmes pour un point très simple point, c'est à dire le temps nécessaire pour garantir l'absence de collisions en vaut pas la chandelle. Vous pourriez avoir simplement dit que, au lieu d'inventer hypothétique des algorithmes qui prennent juste le temps de faire qu'il ne vaut pas tout. Bonne chagrin.
J'ai interprété votre réponse originale à cette question comme une déclaration générale qui efficace algorithmes de hachage doit mapper chaque distincts de l'objet à un autre hashcode; aucun algorithme ne parvient pas à le faire est inefficace. Que l'énoncé est faux. Efficace des codes de hachage sont attendus pour l'occasion, des collisions de hachage; dans de nombreux cas, il est impossible d'éliminer toutes les collisions, et même quand il n'est pas impossible, il est rarement la peine pour rien, mais le plus simple des types.
OriginalL'auteur Tundey