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?
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é.
Les docs sont assez clairs à ce sujet: HashSet.add
ne 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.put
va remplacer:
Si la carte contenait précédemment un mappage pour la clé, l'ancienne valeur est remplacée.
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. "
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.
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.
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.
Vous devez d'abord vérifier la méthode put dans la carte de hachage, car HashSet est sauvegardé par HashMap.