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 valuev
such that(key==null ? k==null : key.equals(k))
, then this method returnsv
; otherwise it returnsnull
. (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 tonull
. The containsKey operation may be used to distinguish these two cases.Parameters:
key
- the key whose associated value is to be returnedReturns:
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
?
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.
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.
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. ;)
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With