Java7 WeakHashMap isEmpty()似乎是错误的

Java7 WeakHashMap isEmpty()似乎是错误的,java,weakhashmap,Java,Weakhashmap,我试图使用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<>();

我试图使用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);
    }

}
import java.util.Map;
导入java.util.WeakHashMap;
公开课考试
{
公共静态void main(最终字符串[]args)
{
最终地图=新的WeakHashMap();
字符串b=新字符串(“b”);
map.put(b,true);
b=零;
gc();
System.out.println(map.isEmpty());
System.out.println(map.keySet().isEmpty());
系统输出打印项次(map);
}
}
实际结果是:

假的

真的

{}

就是说,

map.isEmpty()和map.keySet().isEmpty()不一致。
有人能帮我理解吗?非常感谢。

您应该阅读以下的javadoc:

WeakHashMap
类的行为部分取决于垃圾收集器的操作,因此一些熟悉的(尽管不是必需的)
Map
不变量不适用于此类。因为垃圾收集器可以随时丢弃密钥,
WeakHashMap
的行为可能就好像未知线程正在静默地删除条目一样。特别是,即使您在一个
WeakHashMap
实例上同步,并且没有调用它的任何一个mutator方法,随着时间的推移,
size
方法可能返回较小的值,
isEmpty
方法返回
false
,然后返回
true
对于
containsKey
方法,用于返回给定键的
true
和更高版本的
false
,对于
get
方法,用于返回给定键的值,但稍后返回
null
,对于
put
方法返回
null
remove
方法返回
false
,对于之前出现在映射中的键,对于键集、值集合和条目集的连续检查,以产生连续较小的元素数

总之,你所看到的效果是完全有效的。

说:

…此结果是快照,可能不会反映未处理的条目 将在下次尝试访问之前删除,因为它们不是 引用时间更长

因此,您可能希望
isEmpty()
在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());
    }

}

来自类的Java 8 API文档:“由于垃圾收集器可能随时丢弃密钥,WeakHashMap的行为可能就好像未知线程正在静默地删除条目一样。”和“.size方法可能随时间返回较小的值,isEmpty方法可能返回false,然后返回true…”,所以我看不出有什么理由担心
false
true
true