web-dev-qa-db-fra.com

La modification de la valeur après son placement dans HashMap modifie le contenu de HashMap?

Si je crée un nouveau HashMap et une nouvelle liste, puis que je place la liste à l'intérieur du Hashmap avec une clé arbitraire et que j'appelle plus tard List.clear() cela affectera-t-il ce que j'ai placé à l'intérieur du HashMap?

La question la plus profonde ici étant: lorsque j'ajoute quelque chose à un HashMap, un nouvel objet est-il copié et placé ou une référence à l'objet d'origine est-elle placée?

Merci!

35
Diego

Ce qui se passe ici, c'est que vous placez un pointeur sur une liste dans la table de hachage, pas la liste elle-même.

Lorsque vous définissez

List<SomeType> list;

vous définissez un pointeur sur une liste, pas une liste elle-même.

Quand tu fais

map.put(somekey, list);

vous stockez simplement une copie du pointeur , pas la liste.

Si, ailleurs, vous suivez ce pointeur et modifiez l'objet à sa fin, toute personne détenant ce pointeur fera toujours référence au même objet modifié.

Veuillez consulter http://javadude.com/articles/passbyvalue.htm pour plus de détails sur la valeur de passage en Java.

46

Java est passe-par-référence-par-valeur.

L'ajout de la liste à la carte de hachage ajoute simplement la référence à la carte de hachage, qui pointe vers la même liste. Par conséquent, l'effacement direct de la liste effacera en effet la liste à laquelle vous faites référence dans la table de hachage.

12
James Camfield

Lorsque j'ajoute quelque chose à un HashMap, un nouvel objet est-il copié et placé ou une référence à l'objet d'origine est-elle placée?

C'est toujours une référence à l'objet. Si vous effacez le HashMap, l'objet sera toujours "vivant". Ensuite, l'objet sera détruit par le garbage collector si personne ne le référence plus. Si vous devez le copier, jetez un œil à la méthode Object.clone () et à l'interface Cloneable

5
daitangio
Map<Integer, Integer> hasmapA = new HashMap<>();
hasmapA.put("key1", "value1");
hasmapA.put("key2", "value2");
hasmapA.put("key3", "value3");
  1. Copier par référence: Si vous attribuez un HashMap à un autre, les deux points à la même référence en mémoire.

    Map hasmapB;

    hashmapB = hashmapA;

Si vous apportez des modifications à l'un de ces éléments, les modifications se refléteront dans les deux HashMap car les deux font référence au même emplacement.

  1. Copier par valeur: Si vous souhaitez

cloner/copier en profondeur/créer un emplacement de mémoire séparé/créer un objet séparé

de hashmapB lors de la copie du contenu de hashmapA

Map<Integer, Integer> hashmapB = new HashMap<>();;

hashmapB.putAll(hashmapA)

Remarque: ** Avez-vous remarqué une différence dans les deux points pour la déclaration hashmapB? Au deuxième point, nous devons appeler le constructeur ** HashMap . Pour que nous puissions mettreAll les données de hashmapA dans hashmapB.

Référence

2
Taimoor Changaiz

La réponse correcte à cela est expliquée ci-dessous: Supposons que vous ayez un HashMap appelé hashmap et initialement vous mettez une paire de valeurs clés dans ce HashMap, par ex. hashmap <"test1", "test2">. Après cela, lorsque vous transmettez cette table de hachage à une fonction où vous modifiez à nouveau sa valeur en test3 comme hashmap.put ("test1", "test3") et imprimez à nouveau la carte dans la méthode principale, la Java = Le concept Pass by Value échoue ici.

La raison est la suivante: lorsque vous utilisez HashMap, il effectue le hachage de la clé (test1) et stocke la valeur. Lorsque vous l'avez passé à la fonction où il modifie à nouveau sa valeur, il effectue à nouveau le hachage pour la même clé et obtient la même adresse mémoire et modifie la valeur en conséquence. C'est pourquoi lorsque vous essayez de récupérer la clé "test1" cela vous donne le résultat "test3"

1
Shashank Agrawal

Essaye le

 package test32; 
 
 import Java.util.ArrayList; 
 import Java.util.HashMap; 
 import Java.util.List; 
 
 classe Foo {
 public Foo (int id, nom de chaîne) {
 this.id = id; 
 this.name = name; 
} 
 
 public static void main (String [] args) {
 HashMap strs = new HashMap (); 
 
// créer une liste d'objets 
 List ls = new ArrayList (); 
 ls.add (new Foo (1, "Stavros")); 
 ls.add (new Foo (2, "Makis")); 
 Ls.add (nouveau Foo (3, "Teo")); 
 Ls.add (nouveau Foo (4, "Jim"))); 
 
 // copie les références des objets de la liste vers la table de hachage 
 strs.put ("1", ls.get (0)); 
 strs.put (" 2 ", ls.get (1)); 
 Strs.put (" 3 ", ls.get (2)); 
 Strs.put (" 4 ", ls.get (3 )); 
 
 System.out.println ("liste avant modification:" + ls); 
 System.out.println ("carte avant modification:" + strs); 
 // récupère un objet de la table de hachage 
 Foo f = strs.get ("1"); 
 // définit un di fferent value 
 f.setId (5); 
 // observer que les différences sont reflétées dans la liste et dans la table de hachage également 
 System.out.println ("liste après modification) : "+ ls); 
 System.out.println (" mappage après modification: "+ strs); 
} 
 
 int int privé; 
 public void setId (int id) {
 this.id = id; 
} 
 public int getId () {
 renvoie this.id; 
} 
 
 nom de chaîne privé; 
 public void setName (nom de chaîne) {
 this.name = nom; 
} 
 chaîne publique getName () {
 renvoie ce.nom; 
} 
 
 chaîne publique toString () {
 StringBuilder sb = nouveau StringBuilder (); 
 Sb.append (id); 
 Sb.append ("-"); 
 Sb.append (nom); 
 Return sb. toString (); 
} 
} 
1
stavros

Généralement, vous traitez toujours les références dans Java (sauf si vous créez explicitement un nouvel objet vous-même avec "new" [1]).

Il s'agit donc d'une référence et non d'une copie d'objet complète que vous avez stockée dans la carte, et la modification de la liste affectera également ce que vous voyez lorsque vous parcourez la carte.

C'est une fonctionnalité, pas un bug :)

[1] Les puritains incluront "clone ()" et la sérialisation, mais pour la plupart Java code "nouveau" est le moyen d'obtenir des objets.