r01f.types.collections
Class SoftHashMap<K,V>

java.lang.Object
  extended by java.util.AbstractMap<K,V>
      extended by r01f.types.collections.SoftHashMap<K,V>
All Implemented Interfaces:
java.util.Map<K,V>

public final class SoftHashMap<K,V>
extends java.util.AbstractMap<K,V>

Cache de objetos respaldada por un mapa de objetos SoftReference IMPORTANTE: Diferencia entre objetos StrongReference, WeakReference y SoftReference - Una StrongReference es una referencia java "normal": StringBuffer sb = new StringBuffer(""); sb es una StrongReference al StringBuffer recien creado Si un objeto es "alcanzable" por una cadena de StrongReferences, entonces NO es procesado por el GC OJO!! Cuando un objeto se indexa en un mapa se establece una StrongReference al mismo map.put(key,obj) :< obj tiene una StrongReference y NO es limpiado por el GC - Una WeakReference es una referencia a un objeto que permite al GC liberar el objeto al que referencia la WeakReference WeakReference wr = new WeakReference(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 Class Summary
private static class SoftHashMap.Entry<K,V>
          Encapsula un Map.Entry en un SoftReference
private  class SoftHashMap.EntryIterator
           
private  class SoftHashMap.EntrySet
           
private  class SoftHashMap.HashIterator<T>
           
private  class SoftHashMap.KeyIterator
           
private  class SoftHashMap.KeySet
           
private static class SoftHashMap.SimpleEntry<K,V>
           
private  class SoftHashMap.ValueIterator
           
private  class SoftHashMap.Values
           
 
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
<K> K
_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
<K> K
_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
 

Field Detail

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
Constructor Detail

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 inicial
loadFactor - 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
Method Detail

_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)