¿Se recopilará una entrada de WeakHashMap si el valor contiene la única referencia sólida a la clave?

Necesito asociar algunos datos con una clave durante su vida útil, por lo que estoy usando un WeakHashMap. Sin embargo, además necesito obtener una clave por su valor correspondiente. La forma más sencilla de hacerlo es aferrarse a la referencia al crear un valor:

public class Key {}

public class Value { 
    final public Key key;
    public Value(Key k) {
        key = k;
    }
}

Por supuesto, mientras uso Value en mi programa, es key no se irá. Sin embargo, si no hay más referencias a ninguna de las claves o su valor fuera del mapa, ¿se recolectará la basura? ¿O la fuerte referencia sobreviviente en el valor lo impide?

preguntado el 08 de noviembre de 11 a las 14:11

2 Respuestas

No, no se recogerá basura, consulte el Javadoc:

Nota de implementación: los objetos de valor en un WeakHashMap se mantienen mediante referencias fuertes ordinarias. Por lo tanto, se debe tener cuidado para garantizar que los objetos de valor no se refieran fuertemente a sus propias claves, ya sea directa o indirectamente, ya que eso evitará que las claves se descarten.

Como lo menciona @biziclop, una solución sería almacenar una referencia débil a la clave en su objeto de valor.

public class Value { 
  final public WeakReference<Key> key;
  public Value(Key k) {
    this.key = new WeakReference<Key>(k);
  }
}

respondido 08 nov., 11:19

@biziclop También del Javadoc: una forma de lidiar con esto es ajustar los valores dentro de WeakReferences antes de insertar, como en: m.put (key, new WeakReference (value)), y luego desenvolver en cada get. ¡Eso debería hacer el truco! - laguille

O eso o solo almacena una referencia débil a la clave en tus objetos de valor. Porque si envuelve el valor en un WR, podría terminar con una clave existente con el valor ya recopilado. - biziclop

En cuanto a la implementación, la respuesta parece ser no.

Esto es del WeakHashMap fuente:

/**
 * The table, resized as necessary. Length MUST Always be a power of two.
 */
private Entry[] table;

...

private static class Entry<K,V> extends WeakReference<K> implements Map.Entry<K,V> {
    private V value;
    ...
}

Como se puede ver, Entry los objetos están fuertemente referenciados por el mapa en sí. Entonces, si el mapa es accesible, también lo será el Entry, por lo tanto tu Value objetos y su clave también.

respondido 08 nov., 11:18

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.