有什么办法如何让从钥匙(或整个条目)HashMap(或其他合适的Map)有效?
在有人说之前,我从不需要它:我做到了.我有这样的循环
for (long i=0; i<1e12; ++i) {
Key key = new Key(i);
Value value = map.get(key);
if (something(key, value)) list.add(key);
}
Run Code Online (Sandbox Code Playgroud)
key如果我可以用list.add(key)类似的东西 代替list.add(map.getKey(key))(新的实例有资格用于GC),我的不必要的记忆可以保存.虽然它们是相同的,但重用旧实例会节省内存.
我知道我可以将钥匙嵌入价值或使用番石榴Interner; 两者都有帮助,但两者都需要一些记忆.
解决一些误解的评论:如果效率没有问题,可以采取以下措施
Key getKeyFromMap(Key key, Map<Key, ?> map) {
for (Key key2 : map.keySet()) {
if (key.equals(key2)) return key2;
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
接受的答案中描述的最有效的解决方案:
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();
}
Run Code Online (Sandbox Code Playgroud)
问题是必须放入package java.util它,因为它使用包私有方法.使用这种方法可能很危险,但在我的"一次运行"用例中没有问题.
为了做到这一点,你准备承诺多少邪恶?
该Map界面不允许您检索密钥或条目.Set界面也没有.HashMap公共界面也不是.
但是HashMap的封装接口不会(在Sun JDK,至少).看看源代码 ; 在第355行,有一个方法被调用getEntry,如下所示:
/**
* 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) {
Run Code Online (Sandbox Code Playgroud)
我相信这正是你所需要的.你可以用反射来调用它,或者将你自己的类偷偷带入java.util包中.Java维护者将来可以采用这种方法,它可能不会出现在所有平台上,但是如果你准备好嗤之以鼻并承担风险,这是一个简单的解决方案.