Why is getEntry(Object key) not exposed on HashMap?
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 implementatio开发者_运维百科n 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?
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;
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.
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.
I stumbled upon this problem recently myself recently. When I boiled the problem down enough, it was that I was essentially using 2 different methods to associate data with the part of the key object that was used for determining equality.
- With the value the key mapped to, via the Map
- With the data contained with the key object, but that wasn't used in the .equals()/hashCode methods, via composition.
I was using a List in the key class to determine equality and hashcode, and there were 3 other fields in it - a boolean, and 2 Strings. In the end, I remade the map as a Map<List<String>, ...> and refactored the other 3 fields into their own class, then had the original class as a composition of the List and the new class. I felt that the code seemed better after this.
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" ?
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.
精彩评论