Использование WeakHashMap?

WeakHashMap-это реализация интерфейса карты, где память объекта value может быть восстановлена сборщиком Grabage если соответствующий ключ больше не упоминается ни в одном разделе программы. Поэтому, если ключ больше не используется в программе. его запись объект будет мусором, собранным независимо от его использования. Все ясно до сих пор

это отличается от HashMap, где объект value остается в HashMap, даже если ключ больше не упоминается. Мы должны явно вызвать метод remove () в объекте HashMap для удаления значения. вызов remove просто удалит запись с карты. Его готовность к GC будет зависит от того, используется ли он где-то в программе или нет.

пожалуйста, найдите этот пример кодирования, объясняющий выше

использование WeakHashMap над HashMap в соответствии с моим пониманием

Я понимаю, что мы должны пойти на WeakHashMap только тогда, когда мы хотим убедиться, что объект value исправлен сборщиком Grabage когда ключ больше не упоминается ни в одном разделе программы. Это делает память программы эффективной, правильно ли я понимаю здесь?

использование WeakHashMap согласно JavaDocs , я мог бы заметить в этом заявлении

этот класс предназначен в первую очередь для использования с ключевыми объектами которого равна методы проверки идентичности объекта с помощью оператора==.

Я не понял, что означало приведенное выше утверждение и как это контрастирует с моим пониманием использования WeakHashMap. На самом деле я не понял, как это утверждение связано с использованием WeakHashMap?

обновление:- на дальнейшее внимательно прочтите ниже заявление javadocs

запись в WeakHashMap будет автоматически удалена, когда ее ключ уже не в обычном использовании. Точнее, наличие сопоставление для данного ключа не будет препятствовать отбрасыванию ключа по сборщик мусора, то есть, сделан finalizable, завершена, и потом исправился. Когда ключ был отброшен, его ввод эффективно удаляется с карты, поэтому этот класс ведет себя несколько иначе, чем другие реализации Карты.

я пересматриваю свое понимание в пользу себя и других

использование WeakHashMap над HashMap в соответствии с моим пересмотренным пониманием

мы должны пойти на WeakHashMap только тогда, когда мы хотим убедитесь, что пара ключ-значение удаляется из карты при запуске GC, когда ключ больше не используется в обычном использовании, кроме самой карты.

примеры :-

    WeakHashMap<Integer, String> numbers = new WeakHashMap<Integer, String>();
    numbers.put(new Integer(1), "one");// key only used within map not anywhere else
    numbers.put(new Integer(2), "two");
    System.out.println(numbers.get(new Integer(1))); // prints "one"
    System.gc();
    // let's say a garbage collection happens here
    System.out.println(numbers.get(new Integer(1))); // prints "null"
    System.out.println(numbers.get(new Integer(2))); // prints "null"


    Object key = new Object();
    m1.put(key, c1);
    System.out.println(m1.size());
    key = null or new Object() ; // privious key only used within map not anywhere else
    System.gc();
    Thread.sleep(100);
    System.out.println(m1.size());

5 ответов


это связано с тем, что объекты будут собирать мусор (GCed), когда они больше не имеют сильной ссылки из любой другой части программы.

дали WeakHashMap<MyObject, String> тогда, если мы делаем следующее:

MyObject mo = new MyObject();
map.put(mo, "Test");
mo = null;

запись mo -> Test будет иметь право на GC. Это означает, что если у вас есть пользовательский .equals реализация, которая использует некоторые свойства MyObject для проверки на равенство, то вы не сможете сделать это:

MyObject mo2 = new MyObject();
map.get(mo2);

потому что даже хотя ваш переопределенный .equals метод может сказать, что mo2.equals(mo) == true это не тот случай, когда mo2 == mo и поэтому запись, возможно, уже была GCed.

дело в том, что если вы держите ссылку на mo и используйте это, чтобы получить значение из Map тогда это тот случай, когда эта ссылка должна

  1. запись mo -> Test не может быть gced
  2. можно использовать == на основе .equals метод получить запись с карты

в основном; поскольку GC будет использовать сильные ссылки для проверки того, может ли объект быть GCed, лучше всего убедиться, что ваш .equals способ делает то же самое, чтобы избежать путаницы.


документация означает, что этот код не очень полезен:

WeakHashMap<Integer, String> numbers = new WeakHashMap<Integer, String>();
numbers.put(new Integer(1), "one");
numbers.put(new Integer(2), "two");
System.out.println(numbers.get(new Integer(1))); // prints "one"
// let's say a garbage collection happens here
System.out.println(numbers.get(new Integer(1))); // prints "null"
System.out.println(numbers.get(new Integer(2))); // prints "null"

это произойдет для любого класса, где разные экземпляры могут быть равны. Javadoc просто предупреждает вас, если вы еще не заметили, что это не полезно.


пройти этот тест

    Object key = new Object();
    WeakHashMap m = new WeakHashMap();
    m.put(key, 1);
    System.out.println(m.size());
    key = null;
    System.gc();
    Thread.sleep(100);
    System.out.println(m.size());

хотя системой.gc не гарантирует запуск GC, но на JVM 7 моего Oracle он всегда работает, и этот тест печатает

1
0

это означает, что GC удалил запись с карты, потому что ключ не ссылается нигде, кроме самой карты


Я думаю, что это означает, что тест объекта на равенство будет использовать местоположение объектов в памяти, а не только потому, что два разных экземпляра "равны" в своих значениях.

Если это не так, трудно сказать, ссылается ли ключ больше и на другие, но "равные" значения, экземпляр может ссылаться и использоваться для поиска значения.

было бы яснее, если бы он сказал, что ключи должны иметь ссылочное равенство, чтобы вы знайте, когда ключи больше не ссылаются ни на что другое, что экземпляр WeakHashMap


основываясь на ответе Евгения Дорофеева, вот пример с несколькими gotchas:

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

public class WeakHashMapTest {

    public static void main(String[] args) throws InterruptedException {
        String key = new String();
        Map<String, String> m = new WeakHashMap();

        m.put(key, "value");
        System.out.println(m.size());

        m.put("key", "value");
        System.out.println(m.size());

        m.put(new String(), "value");
        System.out.println(m.size());

        m.put(new String("k"), "value");
        System.out.println(m.size());

        key = null;
        System.gc();
        Thread.sleep(100);

        System.out.println(m.size());
    }
}

выход

1
2
2
3
1