Is there any way how to get the key (or the whole entry) from a HashMap
(or another suitable Map
) efficiently?
Before somebody says, I never need it: I do. I have a loop like this
for (long i=0; i<1e12; ++i) {
Key key = new Key(i);
Value value = map.get(key);
if (something(key, value)) list.add(key);
}
and my key
needlessly takes memory which could be saved if I could replace list.add(key)
by something like list.add(map.getKey(key))
(the new instance would be eligible for GC). While they're equal, reusing the old instance would save memory.
I know I can embed the key into the value or use Guava's Interner
; both helps, but both also costs some memory.
To address some misunderstanding comments: If efficiency was no issue, the following would do
Key getKeyFromMap(Key key, Map<Key, ?> map) {
for (Key key2 : map.keySet()) {
if (key.equals(key2)) return key2;
}
return null;
}
The most efficient solution as described in the accepted answer:
public static <K, V> K getKey(K key, HashMap<K, V> map) {
final Entry<K, V> entry = map.getEntry(key);
return entry==null ? null : entry.getKey();
}
The problem is that it must be placed into package java.util
as it uses a package private method. It can be dangerous to use such a method, but it's no problem in my "run-once" use case.
How much evil are you prepared to commit in order to do this?
The Map
interface does not let you retrieve a key or an entry. Nor does the Set
interface. Nor does HashMap
's public interface.
But HashMap
's package interface does (in the Sun JDK, at least). Have a look at the source code; at line 355, there is a method called getEntry
which starts like this:
/**
* Returns the entry associated with the specified key in the
* HashMap. Returns null if the HashMap contains no mapping
* for the key.
*/
final Entry<K,V> getEntry(Object key) {
I believe that is exactly what you need. You can call this with reflection, or by sneaking a class of your own into the java.util
package. The Java maintainers could take this method away in the future, and it might not be present on all platforms, but if you're prepared to hold your nose and take the risk, it's a simple solution.
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