3

我的问题是:如何将一堆值与一堆键关联起来

  • 无需直接修改密钥,并且
  • 在不阻止键被 GC 的情况下(知道值对键有强引用)

背景:

我需要将一堆复杂对象(称它们为值)与一些特定对象(称它们为键)相关联。

通常,我这样做的方式是使用关联键和值的哈希图。

这很好用。但是,我还需要确保映射不会干扰键的垃圾收集。换句话说,映射的存在不应阻止密钥被垃圾收集。

通常解决这个问题的方法是使用 Wea​​kHashMap,它只保存对键的 WeakReferences。但是,WeakHashMaps 仅在映射中的值没有对键的强引用时才有效。不幸的是,我的值都对我的键有强引用,这会阻止键被垃圾收集。这也可以通过对值使用弱引用来解决,但这不是一个可行的解决方案,因为我不能让我的值在我的键之前被 GC'd。只要关键对象仍然存在,值也必须存在。

因此,对于这种情况,我的典型解决方案是停止使用 HashMap,而是修改键以对它需要的所有值进行强引用。这将确保我仍然可以获得给定键的所有值,但不会阻止该键在其自然生命周期完成时被 GC。

不幸的是,我无法修改键,因此无法将值直接添加到键中。那么还有哪些聪明的解决方案呢?

4

2 回答 2

2

给定约束:

  • 键对值有某种引用
  • 这些值对键有很强的引用
  • 不要阻止密钥被 GC'd
  • 值不能在键之前被 GC
  • 只要值的键存在,该值也必须存在
  • 值和键仍应支持 GC

...我认为这在逻辑上是不可能的。

为什么你不能删除值→键映射(或者至少使用引用不同但逻辑上.equal()的对象)然后使用WeakHashMap解决方案?

于 2012-04-17T18:08:40.397 回答
0

基本上,您的问题的解决方案是:
1. 从您的值中维护对键的弱引用,因此键可以是 Gc'd
2. 使用 Wea​​kHashMap 将键映射到值(如果存在,则值不会被 GC'd强烈引用其密钥)。

下面是一个示例应用程序来解释我上面提到的设计:

public class WeakApp {

WeakHashMap<Key,Value> weakHashMap = new WeakHashMap<Key,Value> ();
ArrayList <Key> strongReferences = new ArrayList<Key>();

static class Key {
    String smthg = "key";
    public Key(int count) {
        smthg = smthg + count;
    }

    public int hashCode() {
        return smthg.hashCode();
    }

     protected void finalize() {
         System.out.println("Key object " + smthg + " Gc'd");
     }
}

static class Value {

    static int count = 0;
    WeakReference keyReference = null ;
    String smthgValue = "Value object of key ";

    public Value(Key key) {
        keyReference = new WeakReference(key);
        count++;
        smthgValue = smthgValue + key.smthg;

    }
    protected void finalize() {
         System.out.println(" " + smthgValue + " Gc'd");
     }
}

void initValueToKeys(){
    for(int i =0; i< 10; i ++) {
        Key key = new Key(i);
        strongReferences.add(key);
        Value value = new Value(key);
        weakHashMap.put(key, value);
    }
    System.out.println("Weak hash Map size is " + weakHashMap.size());
}

void doMain() {

    System.gc();
    System.runFinalization();

    //Now slowly remove the strong reference keys simulating them going out of use
    Iterator<Key> itr = strongReferences.iterator();

    while(itr.hasNext()){
        Key key = itr.next();
        System.out.println("Removing strong reference to key " + key );
        itr.remove();

    }

    System.gc();
    System.runFinalization();

//shows if any values have references still from keys(should be 0), and expunges stale values to be Gc'd        
    System.out.println("Weak hash Map size is " + weakHashMap.size());

    //give chance for gc to remove the values 
    try {
        Thread.sleep(1000);
    }
    catch(Exception e){
        e.printStackTrace();
    }

    System.gc();
    System.runFinalization();

    System.out.println("System exited");
}

public static void main(String[] args) {
    WeakApp weakApp = new WeakApp();
    weakApp.initValueToKeys();
    weakApp.doMain();
}

}

问候奥斯汀

于 2012-12-01T11:54:33.133 回答