40

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!

0

8 Answers 8

50

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.

9
  • 9
    Sure 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... Commented Jun 1, 2009 at 13:45
  • 1
    Would 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. Commented Jun 1, 2009 at 13:48
  • 4
    There 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. Commented Jun 1, 2009 at 13:50
  • 2
    @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). Commented Jun 1, 2009 at 15:46
  • 3
    People see "reference" and get all confused. That Sun decided to call pointers "reference values" gets "pass-by-reference" into peoples' heads. Commented Jun 1, 2009 at 15:47
13

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.

12
  • 7
    aaaaaaahhhhh!!! No!!!! Java is strictly pass-by-value! See javadude.com/articles/passbyvalue.htm Commented Jun 1, 2009 at 13:34
  • 2
    We know. Java is pass by value. However, saying that can be confusing. Java acts like it is pass by reference.
    – jjnguy
    Commented Jun 1, 2009 at 13:37
  • 1
    Nope - Java does not act that way at all. It acts exactly like C does (which is also pass-by-value) Commented Jun 1, 2009 at 13:40
  • 3
    There'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. Commented Jun 1, 2009 at 13:43
  • 4
    I 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. Commented Jun 1, 2009 at 15:30
5

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

5
Map<Integer, Integer> hasmapA = new HashMap<>();
hasmapA.put("key1", "value1");
hasmapA.put("key2", "value2");
hasmapA.put("key3", "value3");
  1. 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.

  1. 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.

Reference

1

Generally you always deal with references in Java (unless you explicitly create a new object yourself with "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.

3
  • Did you mean "purists"? I've got a picture of the Quaker Oats guy in my mind right now... Commented Jun 1, 2009 at 19:35
  • Whatever :) Me issanot native Englissa speeka.. :-D Commented Jun 2, 2009 at 15:43
  • Other than primitives, you ALWAYS deal with references in Java. A new expression evaluates to a reference.
    – user102008
    Commented Jul 16, 2013 at 8:02
1

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();
    }
}
1

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.

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"

0
-2

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!

10
  • 6
    There 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();"? Commented Jun 1, 2009 at 13:55
  • 4
    @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." Commented Jun 1, 2009 at 15:07
  • 1
    One 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. Commented Jun 1, 2009 at 15:32
  • 3
    -1 java does have pointers, it doesn't have pointer arithmetic.
    – wds
    Commented Apr 28, 2010 at 9:52
  • 1
    @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.
    – Geoff
    Commented Apr 28, 2010 at 9:57

Not the answer you're looking for? Browse other questions tagged or ask your own question.