views:

166

answers:

5

Here is my use case, I have an object that is logically equal to my HashMap key but not the same object (not ==). I need to get the actuall key object out of the HashMap so that i can synchronise on it. I am aware that i can iterate over the ketSet, but this is slow in comparison to hashing.

Looking through the java.util.HashMap implementation i see a getEntry(Object key) method that is exactly what i need. Any idea why this has not been exposed?

Can you think of any other way i can get the key out?

A: 

This sounds like a deeper problem you're heaving. Why do you need such a thing? Why is the key not unique to its object?

What do you mean with "so this i can synchronise on it" ?

Stefan Hendriks
I suspect what is desired is to have all calls for equal objects (i.e. that would map to the same key *within* the hash map), get access to a consistent object obstance for synchronization. The querent hasn't said why he wants this but it sounds like some kind of attempt to prevent two threads from modifying the mapping for a given key at once.
Andrzej Doyle
I think you're right. Using a ConcurrentHashMap could solve his problem, if the assumption about the problem is correct of course :)
Stefan Hendriks
+3  A: 

I can't answer your actual question (why is the method not exposed) beyond the rather obvious, "because the authors decided not to expose it."

However your question leads me to believe that you have a rather strange synchronization scheme going on; from my understanding you're only trying to call it to get a canonical representation of equal objects for synchronization. That sounds like a really bad idea, as I noted in my comment to the question.

A better approach would be to revisit how and why you want to synchronize on these key objects, and rework your synchronization to be clearer and saner, preferably at a level higher up or by using an alternative approach altogether.

It might help if you posted a code snippet of what you want to do with this synchronization so that others can give their opinions on a cleaner way to implement it. One example would simply be to use a thread-safe map class (such as ConcurrentHashMap), if this is indeed what you're trying to achieve here.

Edit: Have a look at How To Ask Questions The Smart Way, in particular the bullet point I've linked as this is a classic example of that deficiency. It seems likely that your overall design is a bit off and needs to go in a different direction; so while you're stuck on this specific issue it's a symptom of a larger problem. Giving us the broader context will lead to you getting much better overall answers.

Andrzej Doyle
+2  A: 

I think you would be better off putting in an extra layer of indirection on the value. The key should also be a "pure" value. Instead of:

Map<ReferenceObjectKey,Thing> map;

Use:

Map<ValueObjectKey,ReferenceObject<Thing>> map;
Tom Hawtin - tackline
That may not necessarily be the problem here - for example, a `String` key would still lead to the same problems declared above (unless you `intern`ed all the Strings which is a bad idea); and I've never heard someone say that Strings are unsuitable map keys.
Andrzej Doyle
I don't follow. `String`s are value objects in my book.
Tom Hawtin - tackline
I'm saying that the problem will still exist with Strings and other value objects; the solution you've proposed won't resolve the issue (asides from the fact that the problem the querent posed is not the one that needs solving anyway).
Andrzej Doyle
I still don't follow.
Tom Hawtin - tackline
A: 

I'm sorry, but you seem to have a conceptual break here.

If your problem is that you "hold" an equivalent object (.equals() is true but == is false) to a key, and need to find the key, using the Object variant of get would not help you, because the only .equals that Object supports is identity (==).

What you need to do is to implement equals() and of course hashcode() in your key class.

This will make it trivial to obtain the entry.

CPerkins
Of course i have implemenented equals and hashcode. My question states that
mR_fr0g
+1  A: 

Actually, the method the caller is asking for would have been useful. It was arguably a mistake that it, or something like it, was not included.

As it is, supposing you wish to increment the Integer value that's mapped from key "a" -- you end up having to do a hash lookup on "a" twice. Supposing you want to distinguish between a value being not present and the value being present but mapped to null -- again, two hash lookups.

In practice the world hasn't ended because of this, though.

Kevin Bourrillion