Java 将值放入 HashMap 后更改值会更改 HashMap 中的内容?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/934775/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Changing value after it's placed in HashMap changes what's inside HashMap?
提问by Diego
If I create a new HashMap and a new List, and then place the List inside the Hashmap with some arbitrary key and then later call List.clear()
will it affect what I've placed inside the HashMap?
如果我创建一个新的 HashMap 和一个新的 List,然后使用一些任意键将 List 放在 Hashmap 中,然后再调用List.clear()
它会影响我在 HashMap 中放置的内容吗?
The deeper question here being: When I add something to a HashMap, is a new object copied and placed or is a reference to the original object placed?
这里更深层次的问题是:当我向 HashMap 添加内容时,是复制并放置了一个新对象,还是放置了对原始对象的引用?
Thanks!
谢谢!
采纳答案by Scott Stanchfield
What's happening here is that you're placing a pointerto a list in the hashmap, not the list itself.
这里发生的事情是你在哈希图中放置了一个指向列表的指针,而不是列表本身。
When you define
当你定义
List<SomeType> list;
you're defining a pointer to a list, not a list itself.
您正在定义指向列表的指针,而不是列表本身。
When you do
当你做
map.put(somekey, list);
you're just storing a copy of the pointer, not the list.
您只是存储指针的副本,而不是列表。
If, somewhere else, you follow that pointer and modify the object at its end, anyone holding that pointer will still be referencing the same, modified object.
如果在其他地方,您跟随该指针并在其末尾修改对象,则持有该指针的任何人仍将引用相同的、修改过的对象。
Please see http://javadude.com/articles/passbyvalue.htmfor details on pass-by-value in Java.
有关 Java 中按值传递的详细信息,请参阅http://javadude.com/articles/passbyvalue.htm。
回答by James Camfield
Java is pass-by-reference-by-value.
Java 是按引用传递值。
Adding the list to the hash map simply adds the reference to hash map, which points to the same list. Therefore, clearing the list directly will indeed clear the list you're referencing in the hashmap.
将列表添加到哈希映射只需添加对哈希映射的引用,该引用指向同一个列表。因此,直接清除列表确实会清除您在哈希图中引用的列表。
回答by GreenieMeanie
Geeze people...everything in Java is pass by value. When you pass an object, the value you are passing is the object reference. Specifically, you are passing a copy of the object reference. There are no pointers in Java either, though references are similar. Get it right!
天哪……Java 中的一切都是按值传递的。传递对象时,传递的值是对象引用。具体来说,您正在传递对象引用的副本。Java 中也没有指针,尽管引用是相似的。修正它!
回答by daitangio
When I add something to a HashMap, is a new object copied and placed or is a reference to the original object placed?
当我向 HashMap 添加内容时,是复制并放置了新对象还是放置了对原始对象的引用?
It is always a reference to the object. If you clear the HashMap the object will be still "live". Then the object will be destroyed by the garbage collector if no one is referencing it anymore. If you need to copy it, take a look to Object.clone() method and to the Cloneable interface
它始终是对对象的引用。如果您清除 HashMap,该对象仍将是“活动的”。如果没有人再引用该对象,则垃圾收集器将销毁该对象。如果您需要复制它,请查看 Object.clone() 方法和 Cloneable 接口
回答by Thorbj?rn Ravn Andersen
Generally you always deal with references in Java (unless you explicitly create a new object yourself with "new" [1]).
通常,您总是在 Java 中处理引用(除非您自己使用“new”[1] 显式创建一个新对象)。
Hence it is a reference and not a full object copy you have stored in the map, and changing the list will also effect what you see when going through the map.
因此,它是一个参考,而不是您存储在地图中的完整对象副本,更改列表也会影响您在浏览地图时看到的内容。
It's a feature, not a bug :)
这是一个功能,而不是一个错误:)
[1] Puritans will include "clone()" and serialization, but for most java code "new" is the way to get objects.
[1] 清教徒将包括“clone()”和序列化,但对于大多数java代码,“new”是获取对象的方式。
回答by stavros
Try it out
试试看
package test32; import java.util.ArrayList; import java.util.HashMap; import java.util.List; class Foo { public Foo(int id, String name) { this.id=id; this.name=name; } public static void main(String[] args) { HashMap strs = new HashMap(); // create a list of objects List ls = new ArrayList(); ls.add(new Foo(1, "Stavros")); ls.add(new Foo(2, "Makis")); ls.add(new Foo(3, "Teo")); ls.add(new Foo(4, "Jim")); // copy references of objects from list to hashmap 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("list before change : " + ls); System.out.println("map before change: " + strs); // get an object from the hashmap Foo f=strs.get("1"); // set a different value f.setId(5); // observe that the differences are reflected to the list and to the hashmap also System.out.println("list after change : "+ls); System.out.println("map after change: "+strs); } private int id; public void setId(int id) { this.id=id; } public int getId() { return this.id; } private String name; public void setName(String name) { this.name=name; } public String getName() { return this.name; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append(id); sb.append("-"); sb.append(name); return sb.toString(); } }
回答by Shashank Agrawal
The Correct answer for this is Explained below : Suppose you have a HashMap called hashmap and initially you put a key value pair in this HashMap e.g. hashmap<"test1","test2">. After this when you pass this hashmap to a function where you again changes its value to test3 like hashmap.put("test1", "test3") and print the map again in main Method, the Java Pass by Value Concept fails here.
对此的正确答案解释如下:假设您有一个名为 hashmap 的 HashMap,并且最初您在此 HashMap 中放置了一个键值对,例如 hashmap<"test1","test2">。在此之后,当您将此哈希图传递给一个函数,在该函数中您再次将其值更改为 test3,如 hashmap.put("test1", "test3") 并在 main 方法中再次打印该映射,Java Pass by Value 概念在这里失败。
The Reason is : When you use HashMap, it does the Hashing for the Key(test1) and store the value. When you passed it to the function where it again changes its value, it again does the hashing for the same key and gets the same memory Address and changes the value Accordingly. Thats why when you try to retreive the key "test1" it gives you the result as "test3"
原因是:当您使用 HashMap 时,它会对 Key(test1) 进行散列并存储值。当您将它传递给函数,它再次更改其值时,它会再次对相同的键进行散列并获取相同的内存地址并相应地更改值。这就是为什么当您尝试检索密钥“test1”时,它会给您结果为“test3”
回答by Taimoor Changaiz
Map<Integer, Integer> hasmapA = new HashMap<>();
hasmapA.put("key1", "value1");
hasmapA.put("key2", "value2");
hasmapA.put("key3", "value3");
Copy By reference:If you assign one HashMapto other then both point to same reference in memory.
Map hasmapB;
hashmapB = hashmapA;
按引用复制:如果将一个HashMap分配给另一个,则两者都指向内存中的相同引用。
地图 hasmapB;
hashmapB = hashmapA;
If you make changes in any of these, changes will reflect in both HashMapas both are referencing to same location.
如果您对其中任何一个进行更改,更改将反映在两个HashMap 中,因为它们都引用了相同的位置。
- Copy By Value:If you wan to
- 按值复制:如果你想
clone/deepcopy/create separate memory location/create separate object
克隆/深度复制/创建单独的内存位置/创建单独的对象
of hashmapB while copying content of hashmapA
复制 hashmapA 的内容时的 hashmapB
Map<Integer, Integer> hashmapB = new HashMap<>();;
hashmapB.putAll(hashmapA)
Note: ** Have you noticed difference in both points for hashmapB declaration? In second point we have to call **HashMapconstructor. So that we can putAlldata of hashmapA into hashmapB.
注意:**您是否注意到 hashmapB 声明的两个点不同?在第二点我们必须调用 **HashMap构造函数。这样我们就可以的putAll到hashmapB hashmapA的数据。