web-dev-qa-db-fra.com

Résolution de collision dans Java HashMap

Java HashMap utilise la méthode put pour insérer la paire K/V dans HashMap. Disons que j'ai utilisé la méthode put et que maintenant HashMap<Integer, Integer> a une entrée avec key comme 10 et value comme 17.

Si j'insère 10,20 dans cette HashMap, elle remplace simplement l'entrée précédente par cette entrée en raison d'une collision en raison de la même clé 10. 

Si la clé entre en collision, HashMap remplace l'ancienne paire K/V par la nouvelle paire K/V. 

Ma question est donc de savoir quand la HashMap utilise la technique de résolution de conflit par chaînage? 

Pourquoi n'a-t-il pas formé une linkedlist avec une clé égale à 10 et une valeur égale à 17,20?

50
user2938723

Lorsque vous insérez la paire (10, 17), puis (10, 20), il n'y a techniquement aucune collision. Vous remplacez simplement l'ancienne valeur par la nouvelle valeur pour une clé donnée 10 (puisque dans les deux cas, 10 est égal à 10 et que le code de hachage pour 10 est toujours 10).

La collision survient lorsque plusieurs clés sont accolées au même compartiment. Dans ce cas, vous devez vous assurer de pouvoir distinguer ces touches. Le chaînage de la résolution des collisions est l’une de ces techniques utilisées à cette fin.

A titre d'exemple, supposons que deux chaînes "abra ka dabra" et "wave my wand" donnent des codes de hachage 100 et 200 respectivement. En supposant que la taille totale du tableau soit 10, les deux se retrouveront dans le même compartiment (100 % 10 et 200 % 10). Le chaînage garantit que chaque fois que vous faites map.get( "abra ka dabra" );, vous vous retrouvez avec la valeur correcte associée à la clé. Dans le cas de hash map en Java, cela est fait en utilisant la méthode equals.

77
Sanjay T. Sharma

Dans HashMap, la clé est un objet contenant les méthodes hashCode() et equals(Object).

Lorsque vous insérez une nouvelle entrée dans la mappe, il vérifie si hashCode est déjà connu. Ensuite, il va parcourir tous les objets avec ce hashcode et tester leur égalité avec .equals(). Si un objet equal est trouvé, la nouvelle valeur remplace l’ancien. Sinon, cela créera une nouvelle entrée dans la carte.

Habituellement, en parlant de cartes, vous utilisez collision lorsque deux objets ont le même hashCode mais ils sont différents. Ils sont stockés en interne dans une liste.

15
Guillaume Poussel

Il aurait pu former une liste chaînée, en effet. C'est juste que le contrat Map exige qu'il remplace l'entrée:

V put(K key, V value)

Associe la valeur spécifiée à la clé spécifiée dans cette mappe (opération facultative). Si la carte contenait précédemment un mappage pour la clé, l'ancienne valeur est remplacée par la valeur spécifiée. (On dit qu'une carte m contient une correspondance pour une clé k si et seulement si m.containsKey (k) renverrait true.)

http://docs.Oracle.com/javase/6/docs/api/Java/util/Map.html

Pour qu'une carte stocke des listes de valeurs, il doit s'agir d'un Multimap. Voici Google: http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Multimap.html

Une collection semblable à une carte, mais pouvant associer plusieurs valeurs à une seule clé. Si vous appelez put (K, V) deux fois, avec la même clé mais avec des valeurs différentes, la carte contient des mappages de la clé aux deux valeurs.

Edition: Résolution de collision

C'est un peu différent. Une collision se produit lorsque deux clés différentes ont le même code de hachage ou si deux clés de codes de hachage différents sont mappées dans le même compartiment du tableau sous-jacent.

Considérez la source de HashMap (morceaux supprimés):

public V put(K key, V value) {
    int hash = hash(key.hashCode());
    int i = indexFor(hash, table.length);
    // i is the index where we want to insert the new element
    addEntry(hash, key, value, i);
    return null;
}

void addEntry(int hash, K key, V value, int bucketIndex) {
    // take the entry that's already in that bucket
    Entry<K,V> e = table[bucketIndex];
    // and create a new one that points to the old one = linked list
    table[bucketIndex] = new Entry<>(hash, key, value, e);
}

Pour ceux qui sont curieux de savoir comment la classe Entry dans HashMap se comporte comme une liste, il s'avère que HashMap définit sa propre classe statique Entry qui implémente Map.Entry. Vous pouvez voir par vous-même en consultant le code source:

GrepCode pour HashMap

9
iluxa

Il y a une différence entre la collision et la duplication . Collision signifie hashcode et le godet est identique, mais en duplicate, ce sera le même hashcode, le même godet, mais ici la méthode equals apparaît. 

Une collision est détectée et vous pouvez ajouter un élément sur une clé existante. mais en cas de duplication, il remplacera la nouvelle valeur.

2

Tout d’abord, vous avez eu l’idée de hacher un peu et cela a été rectifié par M. Sanjay.

Et oui, Java implémente effectivement une technique de résolution de collision. Lorsque deux clés sont hachées à la même valeur (car le tableau interne utilisé est de taille finie et que la méthode hashcode () renvoie la même valeur de hachage pour deux clés différentes), une liste liée est alors formée dans le compartiment emplacement où toutes les informations sont entrées en tant qu'objet Map.Entry contenant une paire clé-valeur. L'accès à un objet via une clé nécessitera au pire O(n) si l'entrée est présente dans de telles listes. La comparaison entre la clé que vous avez passée avec chaque clé de cette liste se fera par la méthode equals ().

Bien que, à partir de Java 8, les listes chaînées soient remplacées par des arbres (O (log n))

2
Rajarshee Mitra

Il n'y a pas de collision dans votre exemple. Vous utilisez la même clé, l'ancienne valeur est remplacée par la nouvelle. Maintenant, si vous utilisiez deux clés mappant le même code de hachage, vous auriez une collision. Mais même dans ce cas, HashMap remplacerait votre valeur! Si vous souhaitez que les valeurs soient chaînées en cas de collision, vous devez le faire vous-même, par exemple. en utilisant une liste comme valeur.

1
Macondo2Seattle

Ce n'est pas défini pour le faire. Pour obtenir cette fonctionnalité, vous devez créer une carte qui mappe les clés sur des listes de valeurs:

Map<Foo, List<Bar>> myMap;

Ou, vous pouvez utiliser le fichier multimédia de Google collections/bibliothèques de goyaves

1
yamafontes

Votre cas ne parle pas de résolution de collision, il s'agit simplement de remplacer l'ancienne valeur par une nouvelle valeur pour la même clé, car la variable HashMap de Java ne peut pas contenir de doublons (c'est-à-dire plusieurs values ​​) pour la même clé

Dans votre exemple, la valeur 17 sera simplement remplacée par 20 pour la même clé 10 dans HashMap.

Si vous essayez de définir une valeur différente/nouvelle pour la même clé, il ne s'agit pas du concept de résolution de collision, mais simplement du remplacement de l'ancienne valeur par une nouvelle valeur pour la même clé. C’est ainsi que HashMap a été conçu et vous pouvez jeter un coup d’œil à l’API ci-dessous (l’accentuation m’appartient) tirée de ici .

public V put (clé K, valeur V) 

Associe la valeur spécifiée à clé spécifiée dans cette carte. Si la carte contenait précédemment un mappage pour la clé, l'ancienne valeur est remplacée


D'autre part, les techniques de résolution de collision n'interviennent que lorsque plusieurs clés se retrouvent avec le même hashcode (c'est-à-dire qu'elles se trouvent au même emplacement de compartiment) où une entrée est déjà stockée. HashMap traite la résolution de la collision en utilisant le concept de chaînage, c'est-à-dire qu'il stocke les valeurs dans une liste liée (ou une arborescence équilibrée depuis Java8, dépend du nombre d'entrées).

0
developer

Lorsque plusieurs clés se retrouvent dans le même code de hachage qui est présent dans le même compartiment . Lorsque la même clé a des valeurs différentes, l'ancienne valeur sera remplacée par la nouvelle valeur.

La liste des éléments appréciés a été convertie en arborescence binaire équilibrée à partir de la version Java 8 dans le pire des cas.

Une collision se produit lorsque deux clés distinctes génèrent la même valeur hashcode () . Lorsqu'il y a plus de collisions, les performances de hashmap sont pires.

Les objets qui sont égaux selon la méthode equals doivent renvoyer la même valeur hashCode . Lorsque les deux objets renvoient le même code, ils seront déplacés dans le même compartiment.

0
RAKESH AKUTHOTA