2015-04-02 197 views
3

如果我将对象添加到HashMap,然后在不再需要时调用remove方法,它是否保证它们释放的资源将被释放(因为没有其他引用)?HashMap.remove和垃圾回收

+1

HashMaps不存储对象。他们可以存储参考。 – immibis 2015-04-02 10:05:18

+1

而不是'HashMap',你可以使用'WeakHashMap'。 – Prashant 2015-04-02 10:05:34

+0

如果您从Map中删除的任何对象有任何过时的引用,那么它将无法启动GC。您需要在删除之前将其设置为空。 – Prashant 2015-04-02 10:13:30

回答

1

不,您可能从别的地方引用了该对象。

简单的例子:

Map < int, Object > map = new HashMap < int, Object >(); 
CustomObject x = new CustomObject(); 
map.put(1, x); 
map.remove(1); 
//you still have access to x 
+0

他的意思是...'map.put(x); x = null; map.remove(x);' – 2015-04-02 10:11:50

+0

@JordiCastilla 'map.remove(x)'其中'x == null'不会按预期工作。 – 2015-04-02 10:12:58

+2

@GoogleHireMe他的意思是map.put(key,x); X = NULL; map.remove(键); – olegst 2015-04-02 10:17:16

4

如果您确定的:

有他们

是任何其它引用,他们候选人GC,这并不意味着他们会立即回忆起来!!

你可以做:

System.gc(); 

但不是一个好主意。欲了解更多信息,请查询thisthis问题。

+0

嗨@olegst如果这个或任何答案已经解决了您的问题,请点击复选标记考虑[接受它](http://meta.stackexchange.com/q/5234/179419)。这向更广泛的社区表明,您已经找到了解决方案,并为答复者和您自己提供了一些声誉。没有义务这样做。 – 2015-04-15 15:42:43

0

如果Map是唯一一个引用Object的对象,并且您从Map中删除了Object引用,那么是的,这个Object不再被任何引用,并且有资格使用GC。一如既往,它所花费的资源将保证被释放,但不能保证何时会发生。

1

垃圾回收总是在所有对象初始化的堆内存中完成。当您在HashMap中调用remove方法时,它只会从中删除id和值,而不是您创建的对象。

2

HashMap条目存储在一个数组中。如果删除一个条目,相关数组的位置将为null。因此,hashMap已不再提及已删除的value对象。

然后垃圾回收的正常规则将应用于value对象。

验证的简单代码。

public class REPL7 { 

    public static void main(String[] args) throws Exception { 
     Map<String, Foo> map = new HashMap(); 
     map.put("one", new Foo("foo one")); 
     map.put("two", new Foo("foo two")); 

     // make the backing array accessible 
     Field field = map.getClass().getDeclaredField("table"); 
     field.setAccessible(true); 
     Object[] obj = (Object[]) field.get(map); 

     // two references to Foo objects will be shown    
     System.out.println("obj = " + Arrays.toString(obj)); 

     map.remove("one"); 

     // only one reference to a Foo object will eb shown 
     System.out.println("obj = " + Arrays.toString(obj)); 
    } 
} 

class Foo { 
    String marker; 

    Foo(String marker) { 
     this.marker = marker; 
    } 

    @Override 
    public String toString() { 
     return "Foo{" + marker + '}'; 
    } 
}