J'ai entendu dans mes classes de diplôme qu'un HashTable
placera une nouvelle entrée dans le seau «prochaine disponible» si la nouvelle entrée de clé entre en collision avec une autre.
Comment le HashTable
toujours renvoie-t-il la valeur correcte si cette collision se produit lors de l'appel d'un retour avec la clé de collision?
Je suppose que le type Keys
sont String
et hashCode()
renvoie la valeur par défaut générée par, par exemple, Java.
Si j'implémente ma propre fonction de hachage et que je l'utilise dans le cadre d'une table de consultation (c.-à-d. A HashMap
ou Dictionary
), quelles stratégies existent pour traiter les collisions?
J'ai même vu des notes relatives aux nombres premiers! Informations pas si claires de la recherche Google.
Lorsque vous avez parlé de "La table de hachage placera une nouvelle entrée dans le compartiment" suivant disponible "si la nouvelle entrée de clé entre en collision avec une autre.", Vous parlez de la stratégie d'adressage ouverte de la résolution de collision de la table de hachage.
Il existe plusieurs stratégies de table de hachage pour résoudre les collisions.
Le premier type de grande méthode nécessite que les clés (ou les pointeurs vers elles) soient stockées dans la table, avec les valeurs associées, ce qui comprend en outre:
Une autre méthode importante pour gérer les collisions est le redimensionnement dynamique , qui a plusieurs façons:
EDIT : les éléments ci-dessus sont empruntés à wiki_hash_table , où vous devriez aller voir pour obtenir plus d'informations.
la source
Il existe plusieurs techniques disponibles pour gérer les collisions. Je vais expliquer certains d'entre eux
Chaînage: Dans le chaînage, nous utilisons des index de tableau pour stocker les valeurs. Si le code de hachage de la deuxième valeur pointe également vers le même index, nous remplaçons cette valeur d'index par une liste liée et toutes les valeurs pointant vers cet index sont stockées dans la liste liée et l'index du tableau réel pointe vers la tête de la liste liée. Mais s'il n'y a qu'un seul code de hachage pointant vers un index de tableau, la valeur est directement stockée dans cet index. La même logique est appliquée lors de la récupération des valeurs. Ceci est utilisé dans Java HashMap / Hashtable pour éviter les collisions.
Sondage linéaire: Cette technique est utilisée lorsque nous avons plus d'index dans la table que les valeurs à stocker. La technique de palpage linéaire fonctionne sur le concept de l'incrémentation continue jusqu'à ce que vous trouviez un emplacement vide. Le pseudo code ressemble à ceci:
Technique de double hachage: Dans cette technique, nous utilisons deux fonctions de hachage h1 (k) et h2 (k). Si la fente à h1 (k) est occupée, la deuxième fonction de hachage h2 (k) est utilisée pour incrémenter l'index. Le pseudo-code ressemble à ceci:
Les techniques de sondage linéaire et de double hachage font partie de la technique d'adressage ouvert et ne peuvent être utilisées que si les emplacements disponibles sont supérieurs au nombre d'éléments à ajouter. Cela prend moins de mémoire que le chaînage car il n'y a pas de structure supplémentaire utilisée ici, mais sa lenteur à cause de beaucoup de mouvement se produit jusqu'à ce que nous trouvions un emplacement vide. Toujours dans la technique d'adressage ouvert lorsqu'un élément est supprimé d'un emplacement, nous mettons une pierre tombale pour indiquer que l'élément est supprimé d'ici, c'est pourquoi il est vide.
Pour plus d'informations, consultez ce site .
la source
Je vous suggère fortement de lire cet article de blog paru récemment sur HackerNews: Comment HashMap fonctionne en Java
En bref, la réponse est
la source
Ceci est en fait pas le cas, au moins pour le JDK Oracle (il est un détail de mise en œuvre qui pourrait varier entre les différentes implémentations de l'API). Au lieu de cela, chaque compartiment contient une liste chaînée d'entrées antérieures à Java 8 et une arborescence équilibrée dans Java 8 ou supérieur.
Il utilise le
equals()
pour trouver l'entrée réellement correspondante.Il existe différentes stratégies de gestion des collisions avec différents avantages et inconvénients. L'entrée de Wikipedia sur les tables de hachage donne un bon aperçu.
la source
Hashtable
etHashMap
dans jdk 1.6.0_22 par Sun / Oracle.public V get(Object key)
ce moment (même version que ci-dessus). Si vous trouvez une version précise où ces listes liées apparaissent, je serais intéressé de savoir.Entry
objets liés :localEntry = localEntry.next
e = e.next
n'est pas++index
. +1Mise à jour depuis Java 8: Java 8 utilise un arbre auto-équilibré pour la gestion des collisions, améliorant le pire des cas de O (n) à O (log n) pour la recherche. L'utilisation d'un arbre auto-équilibré a été introduite dans Java 8 comme une amélioration par rapport au chaînage (utilisé jusqu'à java 7), qui utilise une liste chaînée, et a le pire cas de O (n) pour la recherche (car il doit traverser la liste)
Pour répondre à la deuxième partie de votre question, l'insertion se fait en mappant un élément donné à un index donné dans le tableau sous-jacent de la table de hachage, cependant, lorsqu'une collision se produit, tous les éléments doivent encore être préservés (stockés dans une structure de données secondaire , et pas seulement remplacé dans le tableau sous-jacent). Ceci est généralement fait en faisant de chaque composant de tableau (slot) une structure de données secondaire (aka bucket), et l'élément est ajouté au bucket résidant sur l'index de tableau donné (si la clé n'existe pas déjà dans le bucket, dans dans quel cas il est remplacé).
Pendant la recherche, la clé est hachée sur son index de tableau correspondant et la recherche est effectuée pour un élément correspondant à la clé (exacte) dans le compartiment donné. Étant donné que le compartiment n'a pas besoin de gérer les collisions (compare directement les clés), cela résout le problème des collisions, mais le fait au prix de devoir effectuer une insertion et une recherche sur la structure de données secondaire. Le point clé est que dans un hashmap, la clé et la valeur sont stockées, et donc même si le hachage entre en collision, les clés sont comparées directement pour l'égalité (dans le compartiment) et peuvent donc être identifiées de manière unique dans le compartiment.
La gestion de la collission apporte les pires performances d'insertion et de recherche de O (1) dans le cas de l'absence de gestion de collission à O (n) pour le chaînage (une liste liée est utilisée comme structure de données secondaire) et O (log n) pour arbre auto-équilibré.
Références:
la source
Il utilisera la méthode equals pour voir si la clé est présente paire et surtout s'il y a plus d'un élément dans le même compartiment.
la source
Comme il existe une certaine confusion sur l'algorithme utilisé par HashMap de Java (dans l'implémentation Sun / Oracle / OpenJDK), voici les extraits de code source pertinents (à partir d'OpenJDK, 1.6.0_20, sur Ubuntu):
Cette méthode (cite est des lignes 355 à 371) est appelée lors de la recherche d'une entrée dans le tableau, par exemple from
get()
,containsKey()
et quelques autres. La boucle for parcourt ici la liste chaînée formée par les objets d'entrée.Voici le code des objets d'entrée (lignes 691-705 + 759):
Juste après cela vient la
addEntry()
méthode:Cela ajoute la nouvelle entrée sur le devant du compartiment, avec un lien vers l'ancienne première entrée (ou null, s'il n'y en a pas). De même, la
removeEntryForKey()
méthode parcourt la liste et se charge de ne supprimer qu'une seule entrée, laissant le reste de la liste intact.Donc, voici une liste d'entrées liées pour chaque bucket, et je doute fort que cela ait changé de
_20
à_22
, car c'était comme ça à partir de la 1.2.(Ce code est (c) 1997-2007 Sun Microsystems, et disponible sous GPL, mais pour copier mieux utiliser le fichier original, contenu dans src.zip dans chaque JDK de Sun / Oracle, et aussi dans OpenJDK.)
la source
voici une implémentation très simple de table de hachage en java. dans uniquement les outils
put()
etget()
, mais vous pouvez facilement ajouter ce que vous voulez. il s'appuie sur lahashCode()
méthode de java qui est implémentée par tous les objets. vous pouvez facilement créer votre propre interface,et forcez-le à être implémenté par les touches si vous le souhaitez.
la source
Il existe différentes méthodes de résolution des collisions, parmi lesquelles le chaînage séparé, l'adressage ouvert, le hachage Robin Hood, le hachage de coucou, etc.
Java utilise le chaînage séparé pour résoudre les collisions dans les tables de hachage. Voici un excellent lien pour savoir comment cela se passe: http://javapapers.com/core-java/java-hashtable/
la source