2015-04-02 652 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 + '}'; 
    } 
}