我有一个与讨论过的问题类似的问题 here , 但具有更强的实用性。
例如,我有一个 Map<String, Integer>
,我有一些函数,给它一个键,如果映射的整数值为负,则输入 NULL
到 map :
Map<String, Integer> map = new HashMap<String, Integer>();
public void nullifyIfNegative(String key) {
Integer value = map.get(key);
if (value != null && value.intValue() < 0) {
map.put(key, null);
}
}
在这种情况下,查找(因此,键的 hashCode
计算)进行了两次:一次用于查找,一次用于替换。最好有另一种方法(已经在 HashMap
中)并允许使其更有效:
public void nullifyIfNegative(String key) {
Map.Entry<String, Integer> entry = map.getEntry(key);
if (entry != null && entry.getValue().intValue() < 0) {
entry.setValue(null);
}
}
同样的情况,当你想操作不可变对象(immutable对象)时,它可以是映射值:
-
Map<String, String>
: 我想向字符串值附加一些内容。 -
Map<String, int[]>
: 我想在数组中插入一个数字。
所以这种情况很常见。可能有效但不适合我的解决方案:
- 反射(reflection)。很好,但我不能仅仅为了这个不错的功能而牺牲性能。
- 使用
org.apache.commons.collections.map.AbstractHashedMap
(它至少有protected getEntry()
方法),但不幸的是,commons-collections 不支持泛型。 - 使用generic commons-collections ,但是这个库 (AFAIK) 已经过时(与 Apache 的最新库版本不同步),并且(重要的是)在中央 Maven 存储库中不可用。
- 使用值包装器,这意味着“使值可变”(例如使用可变整数 [例如
org.apache.commons.lang.mutable.MutableInt
] 或集合而不是数组)。这种解决方案会导致内存丧失,我想避免这种情况。 - 尝试扩展
java.util.HashMap
使用自定义类实现(应该在java.util
包中)并将其放入 endorsed folder (因为java.lang.ClassLoader
将拒绝在Class<?> defineClass(String name, byte[] b, int off, int len)
中加载它,请参阅资源),但我不想修补 JDK,而且似乎可以认可的软件包列表不包括java.util
.
类似的问题已经在sun.com bugtracker上提出了,但我想知道,社区的意见是什么,考虑到最大内存和性能效率的出路是什么。
如果您同意,这是一个不错且有益的功能,请为这个错误投票!
最佳答案
从逻辑上讲,您是对的,因为单个 getEntry 将为您节省散列查找。作为一个实际问题,除非您有一个特定的用例,您有理由担心性能影响(这似乎不太可能,散列查找很常见,O(1),并且优化良好)您担心的是可能可以忽略不计。
你为什么不写一个测试?创建一个包含几百万个对象的哈希表,或者比您的应用程序可能创建的对象大一个数量级的任何对象,并平均 get() 的时间超过一百万次左右的迭代(提示:它将是一个非常小的数字)。
您正在做的事情的一个更大问题是同步。您应该知道,如果您在 map 上进行条件更改,您可能会遇到问题,即使您使用的是同步 map ,因为您必须锁定对覆盖 get( ) 和 set() 操作。
关于java - 在 HashMap 中访问隐藏的 getEntry(Object key),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2381000/