Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When a value is added via Map.put(K, V), must the same instance be returned via Map.get(K)?

Suppose you have this code:

Map<Foo, Bar> map = new HashMap<Foo, Bar>();

Foo foo = new Foo();
Bar bar = new Bar();
map.put(foo, bar);

Bar barReturned = map.get(foo);

Does Java require that barReturned == bar? That is, does Java require that barReturned be the same instance as bar? If not, what semantics are expected?

The Javadoc suggests that barReturned == bar must be true, but I'm not 100% sure:

V get(Object key)

Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.

More formally, if this map contains a mapping from a key k to a value v such that (key==null ? k==null : key.equals(k)), then this method returns v; otherwise it returns null. (There can be at most one such mapping.)

If this map permits null values, then a return value of null does not necessarily indicate that the map contains no mapping for the key; it's also possible that the map explicitly maps the key to null. The containsKey operation may be used to distinguish these two cases.

Parameters:

key - the key whose associated value is to be returned

Returns:

THE VALUE TO WHICH THE SPECIFIED KEY IS MAPPED, or null if this map contains no mapping for the key

(Emphasis mine)

Edit: I understand that the implementations of Map that come bundled with the standard library adhere to the barReturned == bar semantics. What I want to know is whether or not this behavior is required as per the documentation. For example, must I also adhere to these semantics if I write my own class that implements Map?

like image 612
Adam Paynter Avatar asked Feb 17 '11 12:02

Adam Paynter


4 Answers

If you are asking whether you can break that relation, i think the answer is "yes". for instance, if you were implementing a Map which acted like a persistent cache, a specific value may be written to disk if not used in a while, then reloaded later. you will not have reference equality in that situation, but that's okay. obviously, you would want to document any deviations from standard behavior, but i don't think this is out of the realm of a reasonable usage of a Map.

like image 139
jtahlborn Avatar answered Nov 06 '22 14:11

jtahlborn


If you interpret the term value used in the javadocs as the reference to the object in the map it would imply that you always need to return the same reference as you put in the map and you would have == equality. Then it becomes more of a question of the definition of the term value used in the docs.

like image 33
K Erlandsson Avatar answered Nov 06 '22 12:11

K Erlandsson


The javadoc does not sate (or limit) it clearly that values that you put in the map are physically equal to those that have been put into it. So I'd dare to say that there is no 100% guarantee, that it must be so. You probably could assume that:

Map<Foo,Bar> map = new HashMap<Foo,Bar>();
Foo foo = new Foo();
Bar bar = new Bar();
map.put(foo, bar);

System.out.println( bar.equals( map.get(foo) ) ); // ==> Should be guaranteed
System.out.println( bar == map.get(foo) );        // ==> no guarantee

You could in theory create a clustered Map implementation that is shared and synchronized on different JVMs, in this case it would be impossible (or at least really difficult) to obtain the same physical instance.

My opinion is that in your implementation you should guarantee that bar.equals( map.get(foo) ) but not necessarly bar == map.get(foo). However as long as you clearly document and state that both of the above is not guaranteed, you can do what you want with your Map implementation. ;)

like image 22
Danilo Tommasina Avatar answered Nov 06 '22 13:11

Danilo Tommasina


If you're implementing your own version of Map, yes you don't need to return the same object instance. There is nothing in the doc and language that requires your implementation to return the same object instance.

Your code might break if and only if there is some library or other parts of your code that made the (unwarranted, though generally reasonable) assumption that the return value will be the same object instance. In this case, well, just don't pass your implementation of Map to that code.

Patient: Doctor, it hurts when I do this
Doctor: Well, don't do that
like image 1
Lie Ryan Avatar answered Nov 06 '22 13:11

Lie Ryan