Reputation: 12664
Take two instances of the same class A, called foo and bar, where:
foo != bar
foo.equals(bar) == true
In other words, foo and bar are different instances but with the same hash code. Now take an instance of Map<A,B>
called "map", where foo is a key in map. Is it possible to retrieve foo from Map, using bar? Currently I iterate through the key set and compare every key but is there a faster way? There don't seem to be any methods in Map for retrieving keys.
I am willing to try any data structure that implements Map or can work like a map.
Why do I want to do this? I'm trying to avoid retaining any more instances than necessary. Once I find foo I can release bar.
Thanks in advance...
Upvotes: 4
Views: 164
Reputation: 261
Just using the existing map to find duplicztes doesn't seem to be enough. Use a second map, where you put(key,key) pairs. Then:
Upvotes: 1
Reputation: 1188
You can refer to the source code of HashMap
If based on your implementation:
foo.hashCode() == bar.hashCode()
and foo.equals(bar)
Then, yes you could directly get the value for key foo
by
map.get(bar)
updated: sorry misunderstanding your question before
if you want to keep the key, why you don't just keep the key cached. Then to retrieve the key is hash tree mapping, should be fast.
HashMap<K,V> map = new HashMap<K,V>();
HashMap<K,K> cacheKeys = new HashMap<K,K>();
cacheKeys.put(foo,foo);
map.put(foo,value);
//now you have var bar; you could retrieve the cached key
bar = cacheKeys.get(bar);//this will make bar = foo; the real bar will be gc
//then get the value
val = map.get(bar);
Upvotes: 0
Reputation: 37875
HashMap actually does have a method to retrieve the entry but it is package-private. I am not really sure why it isn't public to be honest. I don't think it exposes anything. You can, of course, call it with reflection.
Map<String, String> map = new HashMap<String, String>();
map.put(new String("hello"), "world!");
Method method = (
HashMap.class.getDeclaredMethod("getEntry", Object.class)
);
method.setAccessible(true);
@SuppressWarnings("unchecked")
Map.Entry<String, String> entry = (Map.Entry<String, String>)(
method.invoke(map, new String("hello"))
);
System.out.println(entry.toString().replace("=", " ")); // hello world
The reflection probably makes it not useful in the scenario you've described but I guess it could be useful to others. I wouldn't recommend using it.
Upvotes: 1
Reputation: 12993
You can use Apache Commons Collections ™. It has Bidirectional Maps BidiMap
.
These represent maps where the key can lookup the value and the value can lookup the key with equal ease.
BidiMap bidi = new TreeBidiMap();
bidi.put("SIX", "6");
bidi.get("SIX"); // returns "6"
bidi.getKey("6"); // returns "SIX"
bidi.removeValue("6"); // removes the mapping
BidiMap inverse = bidi.inverseBidiMap(); // returns a map with keys and values swapped
Upvotes: 1
Reputation: 35587
This way may faster.
Iterator<A> mapKeyIterator=map.keySet().iterator();
while (mapKeyIterator.hasNext()){
A key;
if((key=mapKeyIterator.next()).equals(bar)) {
return key;
}
}
Upvotes: 0