(obj)
en este caso obj tiene una WeakReference sobre él, lo que permite al GC liberar obj (al llamar a wr.get() se devuelve null)
Un WeakHashMap es un mapa "normal" en el que las CLAVES (no los valores!) son WeakReferences. Cuando las CLAVES dejan de ser utilizadas
(no hay ninguna StringReference sobre ellas), pueden ser liberadas por el GC
Esto hace que un WeakHashMap NO sea la estructura más adecuada para implementar una cache ya que es raro mantener StrongReferences sobre las claves y
por lo tanto las entradas del WeakHashMap son liberadas casi de inmediato (en segundos o milisegundos) si NO se utilizan
- Una SoftReference es como una WeakReference salvo que es menos "propensa" a que el objeto que referencia sea liberado por el GC
* En el caso de una WeakReference sobre un objeto, el GC libera el objeto en cuanto no tiene ninguna StrongReference sobre el mismo
* En el caso de una SoftReference sobre un objeto, el GC libera el objeto en cuanto necesita memoria
Por lo tanto, las SoftReferences son adecuadas para la construcción de caches... en especial mucho más que las WeakReferences puesto que un
WeakHashMap contiene WeakReferences a las CLAVES y normalmente NO se guardan StrongReferences sobre las claves, por lo que enseguida (en el siguiente ciclo GC)
se libera el objeto de la cache. Un SoftHashMap es mucho más adecuado pues la entrada permanece hasta que es necesaria la memoria.
El problema es que la JVM NO proporciona una implementación de un SoftHasMap.
Esta clase es una implementación de la misma en base a la implementacion de WeakHashMap cambiando WeakReference por SoftReference
Así como en el WeakHashMap se guardan WeakReferences a las CLAVES, en esta clase se guardan SoftReferences tambien a las CLAVES
de forma que una clave (y por tanto el objeto referenciado) se liberan en cuanto se necesita memoria, a diferencia de un WeakHashMap
que se libera en cuanto la clave no tiene StrongReferences... es decir, habitualmente muy pronto.
IMPORTANTE!!
El comportamiento de la clase viene determinado por el GC: dado que las entradas
del cache son eliminadas "transparentemente" por el GC, la clase se comporta como si
un thread silenciosamente liberara entradas:
En particular, aunque se haga un synchronize sobre una instancia de SoftCache
y se llame a uno de los método mutadores, es posible obtener resultados "extraños":
- size puede devolver valores distintos
- isEmpty puede devolver primero false y luego true
- containsKey para una clave puede devolver primero true y luego false
- get para una clave puede devolver un valor y luego null
- put puede devolver null y luego un valor
- remove puede devolver false para una clave que anteriormente estaba en el mapa
- En dos examenes sucesiveos keySet, valueSet y entrySet pueden devolver valores distintos (menos elementos)
Nested classes/interfaces inherited from class java.util.AbstractMap
java.util.AbstractMap.SimpleImmutableEntry<K,V>
Field Summary
private java.util.Set<java.util.Map.Entry<K ,V >>
_entrySet
private java.util.Set<K >
_keySet
private float
_loadFactor
private int
_modCount
private java.lang.ref.ReferenceQueue<K >
_queue
cola donde el GC "coloca" los objetos que libera para que se tomen acciones
sobre los mismos; en este caso quitar el objeto del array subyacente
private int
_size
private SoftHashMap.Entry <K ,V >[]
_table
Array subyacente que contiene las entradas del mapa
Las entradas son un objeto Entry que extiende de SoftReference (es decir, la clave es una SoftReference) y que
además almacena:
- El value
- Un hash de la clave
- Una referencia a otro objeto Entry con la misma clave (en realidad el mismo hash de la clave)
(ver metodo PUT)
private int
_threshold
private java.util.Collection<V >
_values
private static int
DEFAULT_INITIAL_CAPACITY
private static float
DEFAULT_LOAD_FACTOR
private static int
MAXIMUM_CAPACITY
private static java.lang.Object
NULL_KEY
Constructor Summary
SoftHashMap ()
Constructor por defecto
SoftHashMap (int initialCapacity)
Constructor en base a la capacidad incial
SoftHashMap (int initialCapacity,
float loadFactor)
Constructor en base a la capacidad inicial y el factor de carga
SoftHashMap (java.util.Map<? extends K ,? extends V > otherMap)
Constructor en base a un mapa de entradas.
Method Summary
private boolean
_containsNullValue ()
private void
_expungeStaleEntries ()
Borra las entradas que el GC ha liberado
NOTA: Cuando el GC libera una WeakReference o SoftReference la mete en una cola
para que alguien (por ejemplo esta clase) tome las acciones pertientes como
es quitar las entradas del array
private SoftHashMap.Entry <K ,V >
_getEntry (java.lang.Object key)
private SoftHashMap.Entry <K ,V >[]
_getTable ()
private static int
_hash (int h)
private static int
_hash (java.lang.Object key)
private static int
_indexFor (int h,
int length)
private void
_init (int initialCapacity,
float loadFactor)
private static
_maskNull (K key)
private SoftHashMap.Entry <K ,V >
_removeMapping (java.lang.Object o)
private void
_resize (int newCapacity)
private void
_transfer (SoftHashMap.Entry <K ,V >[] src,
SoftHashMap.Entry <K ,V >[] dest)
private static
_unmaskNull (K key)
void
clear ()
boolean
containsKey (java.lang.Object key)
boolean
containsValue (java.lang.Object value)
java.util.Set<java.util.Map.Entry<K ,V >>
entrySet ()
private static boolean
eq (java.lang.Object x,
java.lang.Object y)
V
get (java.lang.Object key)
boolean
isEmpty ()
java.util.Set<K >
keySet ()
V
put (K key,
V value)
void
putAll (java.util.Map<? extends K ,? extends V > m)
V
remove (java.lang.Object key)
int
size ()
java.util.Collection<V >
values ()
Methods inherited from class java.util.AbstractMap
clone, equals, hashCode, toString
Methods inherited from class java.lang.Object
finalize, getClass, notify, notifyAll, wait, wait, wait
DEFAULT_INITIAL_CAPACITY
private static final int DEFAULT_INITIAL_CAPACITY
See Also: Constant Field Values
MAXIMUM_CAPACITY
private static final int MAXIMUM_CAPACITY
See Also: Constant Field Values
DEFAULT_LOAD_FACTOR
private static final float DEFAULT_LOAD_FACTOR
See Also: Constant Field Values
NULL_KEY
private static final java.lang.Object NULL_KEY
_table
private SoftHashMap.Entry <K ,V >[] _table
Array subyacente que contiene las entradas del mapa
Las entradas son un objeto Entry que extiende de SoftReference (es decir, la clave es una SoftReference) y que
además almacena:
- El value
- Un hash de la clave
- Una referencia a otro objeto Entry con la misma clave (en realidad el mismo hash de la clave)
(ver metodo PUT)
_size
private int _size
_threshold
private int _threshold
_loadFactor
private float _loadFactor
_queue
private final java.lang.ref.ReferenceQueue<K > _queue
cola donde el GC "coloca" los objetos que libera para que se tomen acciones
sobre los mismos; en este caso quitar el objeto del array subyacente
_modCount
private volatile int _modCount
_entrySet
private transient java.util.Set<java.util.Map.Entry<K ,V >> _entrySet
_keySet
private transient volatile java.util.Set<K > _keySet
_values
private transient volatile java.util.Collection<V > _values
SoftHashMap
public SoftHashMap ()
Constructor por defecto
SoftHashMap
public SoftHashMap (int initialCapacity,
float loadFactor)
Constructor en base a la capacidad inicial y el factor de carga
Parameters: initialCapacity - capacidad inicialloadFactor - factor de carga
SoftHashMap
public SoftHashMap (int initialCapacity)
Constructor en base a la capacidad incial
Parameters: initialCapacity - capacidad inicial
SoftHashMap
public SoftHashMap (java.util.Map<? extends K ,? extends V > otherMap)
Constructor en base a un mapa de entradas.
La capacidad inicial del mapa es la suficiente como para contener las entradas
del mapa que se pasa como parametro
Parameters: otherMap - el mapa de entradas
_init
private void _init (int initialCapacity,
float loadFactor)
size
public int size ()
Specified by: size in interface java.util.Map<K ,V >Overrides: size in class java.util.AbstractMap<K ,V >
isEmpty
public boolean isEmpty ()
Specified by: isEmpty in interface java.util.Map<K ,V >Overrides: isEmpty in class java.util.AbstractMap<K ,V >
get
public V get (java.lang.Object key)
Specified by: get in interface java.util.Map<K ,V >Overrides: get in class java.util.AbstractMap<K ,V >
put
public V put (K key,
V value)
Specified by: put in interface java.util.Map<K ,V >Overrides: put in class java.util.AbstractMap<K ,V >
containsKey
public boolean containsKey (java.lang.Object key)
Specified by: containsKey in interface java.util.Map<K ,V >Overrides: containsKey in class java.util.AbstractMap<K ,V >
putAll
public void putAll (java.util.Map<? extends K ,? extends V > m)
Specified by: putAll in interface java.util.Map<K ,V >Overrides: putAll in class java.util.AbstractMap<K ,V >
remove
public V remove (java.lang.Object key)
Specified by: remove in interface java.util.Map<K ,V >Overrides: remove in class java.util.AbstractMap<K ,V >
clear
public void clear ()
Specified by: clear in interface java.util.Map<K ,V >Overrides: clear in class java.util.AbstractMap<K ,V >
containsValue
public boolean containsValue (java.lang.Object value)
Specified by: containsValue in interface java.util.Map<K ,V >Overrides: containsValue in class java.util.AbstractMap<K ,V >
keySet
public java.util.Set<K > keySet ()
Specified by: keySet in interface java.util.Map<K ,V >Overrides: keySet in class java.util.AbstractMap<K ,V >
values
public java.util.Collection<V > values ()
Specified by: values in interface java.util.Map<K ,V >Overrides: values in class java.util.AbstractMap<K ,V >
entrySet
public java.util.Set<java.util.Map.Entry<K ,V >> entrySet ()
Specified by: entrySet in interface java.util.Map<K ,V >Specified by: entrySet in class java.util.AbstractMap<K ,V >
_expungeStaleEntries
private void _expungeStaleEntries ()
Borra las entradas que el GC ha liberado
NOTA: Cuando el GC libera una WeakReference o SoftReference la mete en una cola
para que alguien (por ejemplo esta clase) tome las acciones pertientes como
es quitar las entradas del array
_getTable
private SoftHashMap.Entry <K ,V >[] _getTable ()
_getEntry
private SoftHashMap.Entry <K ,V > _getEntry (java.lang.Object key)
_resize
private void _resize (int newCapacity)
_transfer
private void _transfer (SoftHashMap.Entry <K ,V >[] src,
SoftHashMap.Entry <K ,V >[] dest)
_removeMapping
private SoftHashMap.Entry <K ,V > _removeMapping (java.lang.Object o)
_containsNullValue
private boolean _containsNullValue ()
_maskNull
private static <K> K _maskNull (K key)
_unmaskNull
private static <K> K _unmaskNull (K key)
eq
private static boolean eq (java.lang.Object x,
java.lang.Object y)
_indexFor
private static int _indexFor (int h,
int length)
_hash
private static int _hash (java.lang.Object key)
_hash
private static int _hash (int h)