web-dev-qa-db-fra.com

L'ajout d'une valeur en double à un HashSet/HashMap remplace-t-il la valeur précédente

Veuillez considérer le code ci-dessous:

HashSet hs = new HashSet();
hs.add("hi"); -- (1)
hs.add("hi"); -- (2)

hs.size() donnera 1 car HashSet n'autorise pas les doublons, donc un seul élément sera stocké.

Je veux savoir si nous ajoutons l'élément dupliqué, cela remplacera-t-il l'élément précédent ou ne l'a-t-il pas ajouté? 

De plus, que se passera-t-il en utilisant HashMap pour le même cas?

114
Anand

Dans le cas de HashMap , il remplace l'ancienne valeur par la nouvelle. 

Dans le cas de HashSet , l'élément n'est pas inséré.

205
Keppil

La première chose que vous devez savoir est que HashSet agit comme une Set, ce qui signifie que vous ajoutez votre objet directement à la HashSet et qu'il ne peut pas contenir de doublons. Vous ajoutez simplement votre valeur directement dans HashSet

Cependant, HashMap est un type Map. Cela signifie que chaque fois que vous ajoutez une entrée, vous ajoutez une paire clé-valeur.

Dans HashMap, vous pouvez avoir des valeurs en double, mais pas des clés en double. Dans HashMap, la nouvelle entrée remplacera l'ancienne. L'entrée la plus récente sera dans la HashMap.

Comprendre le lien entre HashMap et HashSet:

Rappelez-vous, HashMap ne peut pas avoir des clés en double. Derrière la scène, HashSet utilise HashMap.

Lorsque vous essayez d'ajouter un objet dans une HashSet, cette entrée est en fait stockée en tant que clé dans la HashMap - la même HashMap qui est utilisée derrière la scène de HashSet. Puisque cette variable HashMap sous-jacente nécessite une paire clé-valeur, une valeur factice est générée pour nous.

Désormais, lorsque vous essayez d'insérer un autre objet en double dans la même HashSet, il tentera à nouveau de l'insérer en tant que clé dans la HashMap située en dessous. Cependant, HashMap ne prend pas en charge les doublons. Par conséquent, HashSet aura toujours pour résultat d'avoir une seule valeur de ce type. En remarque, pour chaque clé en double, étant donné que la valeur générée pour notre entrée dans HashSet est une valeur aléatoire/fictive, la clé n'est pas remplacée du tout. cela sera ignoré car supprimer la clé et rajouter la même clé (la valeur fictive est la même) n'aurait aucun sens.

Résumé:

HashMap autorise les doublons values, mais pas keys. HashSet ne peut pas contenir de doublons. 

Pour déterminer si l'ajout d'un objet est terminé ou non, vous pouvez vérifier la valeur boolean renvoyée lorsque vous appelez .add() et voir si elle renvoie true ou false. S'il a retourné true, il a été inséré.

41
Jimmy

Les docs sont assez clairs à ce sujet: HashSet.addne remplace pas:

Ajoute l'élément spécifié à cet ensemble s'il n'est pas déjà présent. Plus formellement, ajoute l'élément spécifié e à cet ensemble si cet ensemble ne contient aucun élément e2 tel que (e == null? E2 == null: e.equals (e2)). Si cet ensemble contient déjà l'élément, l'appel le laisse inchangé et renvoie la valeur false. 

Mais HashMap.putva remplacer:

Si la carte contenait précédemment un mappage pour la clé, l'ancienne valeur est remplacée. 

17
pb2q

Dans le cas de HashSet, il ne le remplace pas.

De la docs:

http://docs.Oracle.com/javase/6/docs/api/Java/util/HashSet.html#add(E )

"Ajoute l'élément spécifié à cet ensemble s'il n'est pas déjà présent. Plus formellement, ajoute l'élément spécifié e à cet ensemble si cet ensemble ne contient aucun élément e2 tel que (e == null? E2 == null: e.equals ( e2)). Si cet ensemble contient déjà l'élément, l'appel le laisse inchangé et renvoie false. "

4
Bob Provencher

Corrigez-moi si je me trompe, mais vous voulez en venir avec des chaînes: "Salut" == "Salut" n'est pas toujours vrai (car ce n'est pas nécessairement le même objet).

Si vous obtenez une réponse de 1, c'est parce que la machine virtuelle Java réutilisera les objets chaînes si possible. Dans ce cas, la machine virtuelle Java réutilise l'objet chaîne et remplace donc l'élément dans Hashmap/Hashset. 

Mais vous n'êtes pas assuré de ce comportement (car il pourrait s'agir d'un autre objet chaîne ayant la même valeur "Hi"). Le comportement que vous voyez est simplement dû à l'optimisation de la JVM.

1
Nick Rippe

Pour le dire différemment: lorsque vous insérez une paire clé-valeur dans un HashMap où la clé existe déjà (dans un sens, hashvalue () donne la même valeur et égal à () est vrai, mais les deux objets peuvent toujours différer de différentes manières ), la clé n'est pas remplacée mais la valeur est écrasée. La clé est simplement utilisée pour obtenir hashvalue () et trouver la valeur dans la table avec celle-ci . Depuis HashSet utilise les clés d'un HashMap et définit des valeurs arbitraires qui importent peu à l'utilisateur. les éléments de l'ensemble ne sont pas remplacés non plus.

0
Marco Rothley

HashMap contient fondamentalement Entry qui contient ensuite Key(Object) et Value(Object). Intérieurement HashSet sont HashMap et HashMap remplacent des valeurs comme certains d'entre vous l'ont déjà indiqué ... mais remplace-t-il réellement les clés ??? Non ..et c'est le truc ici. HashMap conserve sa valeur en tant que clé dans la variable HashMap sous-jacente et la valeur est simplement un objet factice.Alors si vous essayez de réinsérer la même valeur dans HashMap (clé de la carte sous-jacente). Elle remplace simplement la valeur factice et non la clé (Valeur pour HashSet) .

Regardez le code ci-dessous pour la classe HashSet:

public boolean  [More ...] add(E e) {

   return map.put(e, PRESENT)==null;
}

Ici, e est la valeur pour HashSet mais la clé pour la carte sous-jacente. Et la clé n'est jamais remplacée. J'espère pouvoir dissiper la confusion.

0
Kunal Kumar

Vous devez d'abord vérifier la méthode put dans la carte de hachage, car HashSet est sauvegardé par HashMap.

  1. Lorsque vous ajoutez une valeur en double, dites une chaîne "One" dans HashSet,
  2. Une entrée ("one", PRESENT) sera insérée dans Hashmap (pour toutes les valeurs Ajoutées au jeu, la valeur sera "PRESENT" qui, si de type Object)
  3. Hashmap ajoute l'entrée dans Map et renvoie la valeur, qui est dans ce cas "PRESENT" ou null si Entry n'y est pas.
  4. La méthode add de Hashset renvoie alors true si la valeur renvoyée par Hashmap est égale à Null sinon false, ce qui signifie qu'une entrée existe déjà ...
0
shiv