Changing value after it's placed in HashMap changes what's inside HashMap?
Solution 1
What's happening here is that you're placing a pointer to 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.htm for details on pass-by-value in Java.
Solution 2
Java is pass-by-reference-by-value.
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.
Solution 3
When I add something to a HashMap, is a new object copied and placed or is a reference to the original object placed?
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
Solution 4
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 HashMap to other then both point to same reference in memory.
Map hasmapB;
hashmapB = hashmapA;
If you make changes in any of these, changes will reflect in both HashMap as both are referencing to same location.
- Copy By Value: If you wan to
clone/deepcopy/create separate memory location/create separate object
of hashmapB while copying content of hashmapA
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 **HashMap constructor. So that we can putAll data of hashmapA into hashmapB.
Solution 5
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(); } }
Comments
-
Diego over 4 years
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?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?
Thanks!
-
Scott Stanchfield about 15 yearsaaaaaaahhhhh!!! No!!!! Java is strictly pass-by-value! See javadude.com/articles/passbyvalue.htm
-
jjnguy about 15 yearsWe know. Java is pass by value. However, saying that can be confusing. Java acts like it is pass by reference.
-
Scott Stanchfield about 15 yearsNope - Java does not act that way at all. It acts exactly like C does (which is also pass-by-value)
-
Scott Stanchfield about 15 yearsThere's a huge harm in it. Pass-by-reference semantics allow you to do things like creating a swap method (see my article that I ref in my first comment to this answer); you cannot do that in Java.
-
jjnguy about 15 yearsWell, it seems like it acts like pass by reference, because, people don't see the 'pointer' that is being passed around. It is not an easy topic to wrap ones head around. Lots of people don't know C.
-
Scott Stanchfield about 15 yearsSure there is. Why do you think there's a "new" operator. Please read my article ref'd above - it'll help you understand what Java is really doing. Just because java does not implement pointers the same way C/C++ does doesn't mean it doesn't have pointers. Pascal implemented pointers without artithmetic on them...
-
Scott Stanchfield about 15 yearsYep, it's not easy, which is why I wrote that article. I'm a compiler guy and a teacher; as a compiler guy, the difference is critical to implementation. As a teacher, the difference is critical to proper understanding of the language, especially why you cannot write something like swap(x,y) or have output/variable parameters.
-
James Camfield about 15 yearsWould you like to take this opportunity to make another link to your article? And maybe there is, but the programmer can never see them or use them in Java, so I fail to see the need to talk about them when all we use are References.
-
jjnguy about 15 yearsI don't think it is helpful to argue about it. I like abstracting out the details and thinking about it in the bigger picture. I see where you are coming from and most definitely agree that people 'should' know how it works behind the scenes. But that doesn't mean that they have to know.
-
Scott Stanchfield about 15 yearsThere can never be enough links to it... (I put it in comments to the above answers b/c they were posted first - many people won't read past the first couple answers and simply upvote them). The programmer can very well see the difference -- swap(x,y) and output/variable parameters are two very important language features that exist in some languages (C++, Ada, Pascal for example) but not in Java.
-
Scott Stanchfield about 15 yearsIt's very worth arguing, because it's spreading misinformation and causing confusion with regard to how you can get data out of a method, like why if you have foo(Dog d) and write d = new Dog() inside foo, the dog pointer on the outside does not change.
-
Scott Stanchfield about 15 yearsThere are pointers in Java. What do you think "Dog d;" defines? If it's actually an Object, why can't you ask it to bark without pointing it: "d = new Dog();"?
-
palantus about 15 yearsI think pass-by-reference-by-value is actually a pretty fair representation of the true semantics. Or would you prefer pass-pointer-by-value?
-
GreenieMeanie about 15 yearsUsing the word "pointers" in Java is misleading (and NOT the correct term), giving one the impression of C-style pointers. References are not the same (and you can't manipulate references the same as "pointers"), so let us please refrain from that term in Java.
-
Scott Stanchfield about 15 yearsI wouldn't mind "pass pointer by-value" (note where the hyphen is - when you hyphenate it tends to be looked upon as official jargon). The terms "pass-by-value" and "pass-by-reference" have very specific (and important) meanings. It's really easiest to think of by separating the concepts: 1) Java has pointers 2) the value of a pointer is the target object's location 3) when you pass an arg you're passing a value 4) the target location gets passed/copied to the formal parameter. Thus you end up with the formal param pointing at the same object as the arg.
-
Scott Stanchfield about 15 yearsBy that logic, Pascal and Ada do not have pointers either (they both do, by the way). Not all languages allow pointer arithmetic. C/C++ were not the first languages to use pointers. You can maipulate pointers in Java the same ways you can in many langauges (assign, dereference).
-
GreenieMeanie about 15 yearsBut in Pascal and Ada, they are also called "pointers" if I recall correctly. They are not called pointers in Java.
-
Diego about 15 yearsI'm not really clear why people are disagreeing about this. Isn't this written somewhere final? The different opinions are confusing.
-
Scott Stanchfield about 15 yearsA rose by any other name would smell as sweet... The term "reference" in language design is similar to an alias - you're using more than one name to refer to the same variable. This is actually quite different from what Java does. Sun chose to call them references (a very poor choice, and many agree) as basically PR - they wanted to bill Java as a safe language; "no pointer arithmetic" is a big selling point, and they went overboard. "Dog d" in Java acts exactly the same as "Dog *d" in C++ (with the exception of no arithmetic)
-
user3532201 about 15 years@GreenieMeanie From the JLS, 4.3.1: "The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object."
-
Scott Stanchfield about 15 yearsIt's very clear in the Java Language Specification: java.sun.com/docs/books/jls/third_edition/html/…: "When the method or constructor is invoked (§15.12), the values of the actual argument expressions initialize newly created parameter variables".
-
user3532201 about 15 yearsI don't see what's so hard to get your head around, really. It's a very distinct difference, and the only sticking point is that Sun decided to call pointers "reference values". They mention in the JLS that a reference value is a pointer to an instance or array (4.3.1), and make it pretty clear that method parameters are storing values (4.12.13). Thus, Java has pointers, and is pass-by-value.
-
Scott Stanchfield about 15 yearsOne more note: NullPointerException is a really good example of how they were thinking before the PR machine started grinding. They thought of the concept as pointers, but late in the game decided to change the name and missed a spot... Note that there are language design concepts, and there are specific language designers' namings. Anyone can write a language. And unfortunately, some make naming mistakes.
-
Scott Stanchfield about 15 years@Adam Thanks for pointing out that quote - I hadn't noticed that before
-
user3532201 about 15 years@Diego There are some terminology issues. If you look at the accepted terms, though, rather than what Sun "officially" calls them, it's perfectly clear what is going on. Sun defines the meanings of their names for things by using the accepted terms, in that they explicitly state that a reference is a pointer (JLS 4.3.1).
-
user3532201 about 15 yearsPeople see "reference" and get all confused. That Sun decided to call pointers "reference values" gets "pass-by-reference" into peoples' heads.
-
Scott Stanchfield about 15 yearsDid you mean "purists"? I've got a picture of the Quaker Oats guy in my mind right now...
-
matbrgz about 15 yearsWhatever :) Me issanot native Englissa speeka.. :-D
-
wds about 14 years-1 java does have pointers, it doesn't have pointer arithmetic.
-
Geoff about 14 years@Scott, quite agree, reference types are pointers passed by value, hence we have the NullPointerException for when the pointer is not pointed at a live object. Just because they can't be manipulated except by assignment does not mean they aren't pointers, it just means they are more tightly controlled than C/C++ etc. pointers.
-
Dave almost 12 yearsThis is exactly why the
final
keyword is somewhat meaningless in Java. As is often the idea of immutability. -
Scott Stanchfield over 11 years@HDave - Final affects the pointer or primitive value - it can only be set once, and is very meaningful and useful. Immutable objects, on the other hand, are completely up to the implementation. A good implementation, like java's String class, really ensures that the data held by the object cannot change. Bad implementations may leak underlying details that can be used to change the data. Good implementations are again, meaningful.
-
user102008 almost 11 yearsOther than primitives, you ALWAYS deal with references in Java. A
new
expression evaluates to a reference.