3

当已经有其他实现可用时,需要引入 Weak HashMap。

简而言之,我有两个问题:

  • Why jdk has WeakHashMap when there is HashMap and Concurrent HashMap in java ?

  • What is the use of it in real life applications ?

编辑 :

虽然 WeakHashmap 键是一个弱引用,但它们仍然引用了一些东西,而不是 GC 丢弃 WeakHashMap 中的键。

4

6 回答 6

4

WeakReferences 和 WeakHashMaps 的一种常见用途是向对象添加属性。有时您想向对象添加一些功能或数据,但子类化和/或组合不是一种选择,在这种情况下,显而易见的事情是创建一个哈希图,将您想要扩展的对象链接到您想要添加的属性. 然后,每当您需要该属性时,您都可以在地图中查找它。但是,如果您要添加属性的对象往往会被销毁和创建很多,那么最终您的地图中可能会出现大量旧对象占用大量内存

如果您使用 Wea​​kHashMap 代替,对象将在您的程序的其余部分不再使用它们时立即离开您的地图,这是所需的行为。

a 的键WeakHashMap具有弱引用。如果密钥已被垃圾回收,则WeakHashMap对象中的条目将被自动删除。正常情况下不会发生HashMap。如果密钥被垃圾回收,则不会删除该条目。

在示例中,我采用了 oneHashMap和 one WeakHashMap。我将在两个对象中都放入条目,然后我们将引用键作为null然后垃圾收集。并再次检查条目。在HashMap对象中将存在条目,但在WeakHashMap对象中将不存在条目。

import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;

public class WeakHashMapTest {
    public static void main(String[] args) {
        Map hashMap= new HashMap();

        Map weakHashMap = new WeakHashMap();

        String keyHashMap = new String("keyHashMap");
        String keyWeakHashMap = new String("keyWeakHashMap");

        hashMap.put(keyHashMap, "Ankita");
        weakHashMap.put(keyWeakHashMap, "Atul");
        System.gc();
        System.out.println("Before: hash map value:"+hashMap.get("keyHashMap")+" and weak hash map value:"+weakHashMap.get("keyWeakHashMap"));

        keyHashMap = null;
        keyWeakHashMap = null;

        System.gc();  

        System.out.println("After: hash map value:"+hashMap.get("keyHashMap")+" and weak hash map value:"+weakHashMap.get("keyWeakHashMap"));
    }
}

输出将是:

Before: hash map value:Ankita and weak hash map value:Atul
After: hash map value:Ankita and weak hash map value:null

更多信息:

于 2013-08-27T17:44:14.110 回答
1

与在您决定将其清除之前保存数据的普通集合不同,WeakHashMap 中的数据可能会在任何时间点被删除,并且当 JVM 决定它想要恢复内存时,无需通知。这使它适用于各种缓存目的。

您可以在此处阅读弱引用(以及各种其他相关类型)

于 2013-08-27T17:44:27.327 回答
1

首先,您应该了解WeakReferences的用途。一旦您了解了这一点,那么从文档中阅读WeakedHashMap定义就会清楚地说明其目的

具有弱键的基于哈希表的 Map 实现。WeakHashMap 中的条目在其键不再常用时将被自动删除。更准确地说,给定键的映射的存在不会阻止该键被垃圾收集器丢弃,也就是说,使其可终结,最终确定,然后回收。当一个键被丢弃时,它的条目被有效地从映射中删除,所以这个类的行为与其他映射实现有些不同。

于 2013-08-27T17:44:32.147 回答
0

它们提供了一种使用对象作为键的方法,而无需创建对它的强引用。这是一种很好的做法,您不想妨碍 JVM 垃圾收集对象的能力,但仍希望能够跟踪对象的某些方面。这使得它们非常适合缓存或存储有关对象的元数据。

于 2013-08-27T17:46:22.260 回答
0

您可以将对象用作键而不会阻止其收集。

来自WeakHashMap 文档

当一个键被丢弃时,它的条目被有效地从映射中删除,所以这个类的行为与其他映射实现有些不同。

于 2013-08-27T17:43:49.453 回答
0

从答案来看,唯一的缓存功能是 GC 上的自动驱逐,它可能不会在年轻一代 GC 期间发生,但在老一代 GC 中用于缓存一段时间使用的大文件的用例。该条目是在任何 GC 上被驱逐还是仅在终身代已满时被驱逐?

除了不可预测的驱逐之外,没有可以在地图上指定的大小限制,因此任何具有预定义缓存大小(元素数量和内存大小)以及驱逐策略的缓存库对我来说似乎是一个更好的选择,因为大多数缓存也是包括在堆使用量超过一定大小时减小大小/刷新更多元素的规定。这些还提供了并发期间的一致性。

所以,我想知道除了由于糟糕的设计而导致内存泄漏和错过命中的风险之外,是否还有一个好的用例来使用它。

于 2016-01-02T10:28:49.930 回答