2013-09-23 37 views
6

Trong ví dụ mã sau đây khi các phím được đặt thành rỗng và System.gc() được gọi, WeakHashMap mất tất cả các ánh xạ và được làm trống.WeakHashMap vs HashMap

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 :{}

Khi WeakHashMap được sử dụng cùng với HashMap và các phím được thiết lập để null, các WeakHashMap không mất ánh xạ khóa giá trị của nó.

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; 
} 

} 

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

Câu hỏi của tôi là tại sao không phải là WeakHashMap mất mục của nó trong ví dụ mã thứ hai ngay cả sau khi các phím sẽ bị loại bỏ?

Trả lời

11

A WeakHashMap hủy các mục nhập khi khóa không còn có thể truy cập được từ mã trực tiếp. Vì các HashMap duy trì một tham chiếu cứng cho các phím, các phím vẫn có thể truy cập và các WeakHashMap không loại bỏ các mục.

Vấn đề là hành vi phải làm với các tham chiếu đến các đối tượng chính, không phải giá trị của bất kỳ biến nào có thể có cùng một lúc có tham chiếu đến các khóa.

+0

Tôi thậm chí không bao giờ nghĩ về các biến như chỉ chứa một con trỏ quá, đó là rất nhiều thông tin để biết, cảm ơn! – xorinzor

2

Một đối tượng phải được loại bỏ ở mọi nơi khác, sau đó WeakHashMap xóa đối tượng đó. Giống như một WeakReference mục đích của nó là để nhớ một đối tượng nếu nó vẫn còn được sử dụng. Mà không gây ra rò rỉ bộ nhớ mãi mãi giữ một đối tượng.

Trong ví dụ thiết lập hm = null; để xem sự kỳ diệu của WeakHashMap đang làm sạch.

+0

có, thiết lập 'hm = null' trước 'System.gc()' không xóa WHM. Cảm ơn tôi đã nhận nó. – Nishant

3

Bạn đã thiết null trên con trỏ k1,k2,k3,k4 nhưng HashMapWeakHashMap vẫn chứa tham chiếu đến những Keys. Và bởi vì HashMap có chứa lời giới thiệu, các phiên bản thực tế của Khóa sẽ không bị GC xóa. WeakHashMap vẫn in tất cả chúng.

Thử chạy ví dụ này chỉ với HashMap -> ngay cả khi bạn đã vô hiệu hóa các tham chiếu đó HashMap sẽ vẫn giữ chúng.

0

HashMap chi phối gc (bộ thu gom rác).

gc chi phối WeakHashMap.

Mặc dù chúng tôi thiết lập null trên k1, k2, k3, k4 gc sẽ không loại bỏ từ HashMap nơi như gc loại bỏ tất cả chúng và cho chúng ta bản đồ trống cho WeakHashMap do đó tên WeakHashMap