3 回答
TA贡献1780条经验 获得超1个赞
尝试使用Integer
对象作为 a 的键WeakHashMap
可能会导致一些奇怪的行为。首先,javadoc forWeakHashMap
有以下注释:
此类主要用于其等于方法使用 == 运算符测试对象身份的关键对象。一旦这样的键被丢弃,它就永远不会被重新创建,所以以后不可能在 WeakHashMap 中查找该键,并且会惊讶于它的条目已被删除。此类将与关键对象完美配合,这些对象的 equals 方法不基于对象标识,例如 String 实例。然而,对于这种可重新创建的键对象,自动删除键已被丢弃的 WeakHashMap 条目可能会令人困惑。
考虑以下代码:
WeakHashMap<Integer, String> map = new WeakHashMap<>();
Integer k = Integer.valueOf(9001);
map.put(k, "OVER 9000!?");
while (true)
{
System.out.println(map.get(k));
Thread.sleep(100);
k = Integer.valueOf(9001);
System.gc();
}
循环将从打印“OVER 9000!?”开始,但在第一个循环之后,原始键已被丢弃(即使现在有一个equals对它的键的引用)。结果,如果该键对象被垃圾收集,则条目将从地图中删除,并且循环将开始打印“null”。由于我们System.gc();在丢弃密钥后调用,因此这很可能发生在单个循环之后。
但这并不是Integer作为WeakHashMap密钥使用的问题的结束。如果将上面的值 9001 更改为 1,您会发现行为发生了变化!(可能?这可能取决于实现。)现在,条目永远不会从地图中删除。这是因为整数缓存——Integer.valueOf(1)总是返回相同的Integer实例,但每次都会Integer.valueOf(9001)创建一个新Integer实例。
第二个问题特定于Integer,但第一个问题实际上适用于您尝试在equals不基于 的情况下使用密钥的任何方案==。如果equals 是基于==,那么你的问题并没有真正适用-如果你没有很强的参考钥匙了,也不要紧,是否值被从地图上删除,因为你不再有办法得到它——你不能重新创建一个使用基于身份的平等的密钥。
添加回答
举报