【问题标题】:Java7 WeakHashMap isEmpty() seems wrongJava7 WeakHashMap isEmpty() 似乎是错误的
【发布时间】:2019-08-19 17:05:14
【问题描述】:

我正在尝试使用 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() 不一致。 有人可以帮我理解吗?非常感谢。

【问题讨论】:

  • 来自该类的 Java 8 API 文档:“因为垃圾收集器可能随时丢弃键,所以 WeakHashMap 的行为可能就像未知线程正在默默地删除条目一样。”和“..size 方法可能会随着时间的推移返回更小的值,isEmpty 方法可能会返回 false 然后返回 true..”,所以我认为没有理由担心。
  • 检查this

标签: java weakhashmap


【解决方案1】:

WeakHashMap::isEmpty 说:

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

所以你会期望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());
    }

}

产量:

false
true
true

【讨论】:

    【解决方案2】:

    你应该阅读WeakHashMap的javadoc:

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

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

    【讨论】:

    猜你喜欢
    • 2021-08-16
    • 2023-03-29
    • 2019-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    相关资源
    最近更新 更多