Java7 WeakHashMap isEmpty() 似乎不对
Java7 WeakHashMap isEmpty() seems wrong
我正在尝试使用 Java7 的 WeakHashMap,我发现它的 isEmpty() 方法给我错误的结果。
import java.util.Map;
import java.util.WeakHashMap;
public class Test
{
public static void main(final String[] args)
{
final Map<String, Boolean> map = new WeakHashMap<>();
String b = new String("B");
map.put(b, true);
b = null;
System.gc();
System.out.println(map.isEmpty());
System.out.println(map.keySet().isEmpty());
System.out.println(map);
}
}
实际结果:
错误
正确
{}
也就是说,
map.isEmpty() 和 map.keySet().isEmpty() 不一致。
有人可以帮我理解吗?非常感谢。
你应该阅读 WeakHashMap
:
的 javadoc
The behavior of the WeakHashMap
class depends in part upon the actions of the garbage collector, so several familiar (though not required) Map
invariants do not hold for this class. Because the garbage collector may discard keys at any time, a WeakHashMap
may behave as though an unknown thread is silently removing entries. In particular, even if you synchronize on a WeakHashMap
instance and invoke none of its mutator methods, it is possible for the size
method to return smaller values over time, for the isEmpty
method to return false
and then true
, for the containsKey
method to return true
and later false
for a given key, for the get
method to return a value for a given key but later return null
, for the put
method to return null
and the remove
method to return false
for a key that previously appeared to be in the map, and for successive examinations of the key set, the value collection, and the entry set to yield successively smaller numbers of elements.
总而言之,您看到的效果是完全有效的。
...This result is a snapshot, and may not reflect unprocessed entries
that will be removed before next attempted access because they are no
longer referenced.
所以你会期望 isEmpty()
returns GC 和 访问后的正确值。此代码演示了这一点:
public class Scratch1 {
public static void main(final String[] args) {
final Map<String, Boolean> map = new WeakHashMap<>();
String b = new String("B");
map.put(b, true);
b = null;
System.gc();
// map not internally accessed at this point
System.out.println(map.isEmpty());
// let's access the Map's internals (and hopefully coerce
// it into removing no-longer-referenced keys)
System.out.println(map.keySet()
.isEmpty());
// map HAS now been accessed
System.out.println(map.isEmpty());
}
}
产量:
false
true
true
我正在尝试使用 Java7 的 WeakHashMap,我发现它的 isEmpty() 方法给我错误的结果。
import java.util.Map;
import java.util.WeakHashMap;
public class Test
{
public static void main(final String[] args)
{
final Map<String, Boolean> map = new WeakHashMap<>();
String b = new String("B");
map.put(b, true);
b = null;
System.gc();
System.out.println(map.isEmpty());
System.out.println(map.keySet().isEmpty());
System.out.println(map);
}
}
实际结果:
错误
正确
{}
也就是说,
map.isEmpty() 和 map.keySet().isEmpty() 不一致。 有人可以帮我理解吗?非常感谢。
你应该阅读 WeakHashMap
:
The behavior of the
WeakHashMap
class depends in part upon the actions of the garbage collector, so several familiar (though not required)Map
invariants do not hold for this class. Because the garbage collector may discard keys at any time, aWeakHashMap
may behave as though an unknown thread is silently removing entries. In particular, even if you synchronize on aWeakHashMap
instance and invoke none of its mutator methods, it is possible for thesize
method to return smaller values over time, for theisEmpty
method to returnfalse
and thentrue
, for thecontainsKey
method to returntrue
and laterfalse
for a given key, for theget
method to return a value for a given key but later returnnull
, for theput
method to returnnull
and theremove
method to returnfalse
for a key that previously appeared to be in the map, and for successive examinations of the key set, the value collection, and the entry set to yield successively smaller numbers of elements.
总而言之,您看到的效果是完全有效的。
...This result is a snapshot, and may not reflect unprocessed entries that will be removed before next attempted access because they are no longer referenced.
所以你会期望 isEmpty()
returns GC 和 访问后的正确值。此代码演示了这一点:
public class Scratch1 {
public static void main(final String[] args) {
final Map<String, Boolean> map = new WeakHashMap<>();
String b = new String("B");
map.put(b, true);
b = null;
System.gc();
// map not internally accessed at this point
System.out.println(map.isEmpty());
// let's access the Map's internals (and hopefully coerce
// it into removing no-longer-referenced keys)
System.out.println(map.keySet()
.isEmpty());
// map HAS now been accessed
System.out.println(map.isEmpty());
}
}
产量:
false
true
true