【问题标题】:WeakHashMap vs HashMap弱哈希映射与哈希映射
【发布时间】:2013-09-23 17:14:46
【问题描述】:

在以下代码示例中,当键设置为 null 并调用 System.gc() 时,WeakHashMap 丢失所有映射并被清空。

class WeakHashMapExample {

public static void main(String[] args) {

    Key k1 = new Key("Hello");
    Key k2 = new Key("World");
    Key k3 = new Key("Java");
    Key k4 = new Key("Programming");

    Map<Key, String> wm = new WeakHashMap<Key, String>();


    wm.put(k1, "Hello");
    wm.put(k2, "World");
    wm.put(k3, "Java");
    wm.put(k4, "Programming");
    k1=null;
    k2=null;
    k3=null;
    k4=null;
    System.gc();
    System.out.println("Weak Hash Map :"+wm.toString());

}

}

class Key{

private String key;

public Key(String key) {
    this.key=key;
}

@Override
public boolean equals(Object obj) {
    return this.key.equals((String)obj);
}
@Override
public int hashCode() {
    return key.hashCode();
}
@Override
public String toString() {
    return key;
}

}

Output: Weak Hash Map :{}

WeakHashMapHashMap 一起使用并且键设置为空时,WeakHashMap 不会丢失其键值映射。

class WeakHashMapExample {

public static void main(String[] args) {

    Key k1 = new Key("Hello");
    Key k2 = new Key("World");
    Key k3 = new Key("Java");
    Key k4 = new Key("Programming");

    Map<Key, String> wm = new WeakHashMap<Key, String>();
    Map<Key, String> hm=new HashMap<Key, String>();

    wm.put(k1, "Hello");
    wm.put(k2, "World");
    wm.put(k3, "Java");
    wm.put(k4, "Programming");

    hm.put(k1, "Hello");
    hm.put(k2, "World");
    hm.put(k3, "Java");
    hm.put(k4, "Programming");
    k1=null;
    k2=null;
    k3=null;
    k4=null;
    System.gc();
    System.out.println("Weak Hash Map :"+wm.toString());
    System.out.println("Hash Map :"+hm.toString());
}

}

class Key{

private String key;

public Key(String key) {
    this.key=key;
}

@Override
public boolean equals(Object obj) {
    return this.key.equals((String)obj);
}
@Override
public int hashCode() {
    return key.hashCode();
}
@Override
public String toString() {
    return key;
}

}

输出: Weak Hash Map :{Java=Java, Hello=Hello, World=World, Programming=Programming} Hash Map :{Programming=Programming, World=World, Java=Java, Hello=Hello}

我的问题是,为什么 WeakHashMap 在第二个代码示例中即使在密钥被丢弃后也不会丢失其条目?

【问题讨论】:

    标签: java weakhashmap


    【解决方案1】:

    当密钥不再可以从实时代码强访问时,WeakHashMap 会丢弃条目。由于HashMap 维护对键的硬引用,因此键仍然可以访问,WeakHashMap 不会丢弃条目。

    关键是行为与对键对象的引用有关,而不是与任何可能曾经引用过键的变量的值有关。

    【讨论】:

    • 我从没想过变量也只包含一个指针,这非常有用,谢谢!
    【解决方案2】:

    试试这个 -

    class WeakHashMapExample {
    
    public static void main(String[] args) {
    
        Key k1 = new Key("Hello");
        Key k2 = new Key("World");
        Key k3 = new Key("Java");
        Key k4 = new Key("Programming");
    
        Map<Key, String> hm=new HashMap<Key, String>();   
        hm.put(k1, "Hello");
        hm.put(k2, "World");
        hm.put(k3, "Java");
        hm.put(k4, "Programming");
        k1=null;
        k2=null;
        k3=null;
        k4=null;
        System.gc();
        System.out.println("Hash Map :"+hm);
    
        System.out.println("Same thing with weakHash Map - "); 
    
        k1 = new Key("Hello");
        k2 = new Key("World");
        k3 = new Key("Java");
        k4 = new Key("Programming");
    
        Map<Key, String> wm = new WeakHashMap<Key, String>();
    
        wm.put(k1, "Hello");
        wm.put(k2, "World");
        wm.put(k3, "Java");
        wm.put(k4, "Programming");
        k1=null;
        k2=null;
        k3=null;
        k4=null;
        System.gc();
        System.out.println("Weak Hash Map :"+wm);
    }
    
    }
    
    class Key{
    
    private String key;
    
    public Key(String key) {
        this.key=key;
    }
    
    @Override
    public boolean equals(Object obj) {
        return this.key.equals((String)obj);
    }
    @Override
    public int hashCode() {
        return key.hashCode();
    }
    @Override
    public String toString() {
        return key;
    }
    
    public void finalize() 
    { 
       System.out.println("Finalize method is called"); 
    } 
    
    }
    

    【讨论】:

      【解决方案3】:

      object 必须在其他任何地方丢弃,然后 WeakHashMap 会清除该对象。像 WeakReference 一样,它的目的是记住一个仍在使用的对象。不会导致永远持有对象的内存泄漏。

      在您的示例中设置 hm = null; 以查看 WeakHashMap 清理的魔力。

      【讨论】:

      • 是的,在System.gc() 之前设置hm=null 确实会清除WHM。谢谢,我明白了。
      【解决方案4】:

      您已在指针k1,k2,k3,k4 上设置了null,但HashMapWeakHashMap 仍包含对Keys 的引用。并且因为HashMap 包含引用,所以 GC 不会删除 Keys 的实际实例。 WeakHashMap 仍然打印所有这些。

      尝试仅使用 HashMap 运行此示例 -> 即使您已将这些引用无效,HashMap 仍将保留它们。

      【讨论】:

        【解决方案5】:

        HashMap 支配 gc(垃圾收集器)。

        gc 支配 WeakHashMap。

        即使我们在 k1,k2,k3,k4 上设置了 null,gc 也不会从 HashMap 中删除,因为 gc 会将它们全部删除并为 WeakHashMap 提供空映射,因此名称为 WeakHashMap

        【讨论】:

          【解决方案6】:

          当 JVM 运行垃圾收集器并发现一个没有引用变量的对象时,它将销毁它,但是当该对象充当 HashMap 中的键时,垃圾收集器不会销毁它。在 WeakHashmap 的情况下,如果它没有引用,即使它充当键,它也会破坏对象。在上面的代码中甚至 k1,k2,k3,k4=null

          但是因为这些对象是 hashmap 中的关键,所以它们不会被垃圾回收销毁。 如果你想销毁它,只需将它们从 Hashmap 中删除 设置 hm=null; 然后 System.gc();会破坏 k1,k2,k3,k4

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-10-13
            • 2016-04-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多