Re: Symboltabelle mit WeakReferences? Wie?
- From: Wanja Gayk <brixomatic@xxxxxxxxx>
- Date: Mon, 23 Apr 2007 17:53:36 +0200
nobody@xxxxxxxxx said...
Nimm ne WeakHaskMap
Das funktioniert nur unter ganz bestimmten Bedingungen, siehe Ralfs und
Ingos Beitrag und meine Antworten. Mein Konzept war, dass das Symbol
selbst eine Referenz auf den String hat, der für den Namen steht und
dann hält sich das ganze selbst fest. Du benutzt Zahlen als Keys. Du
benutzt insbesondere eigene Zahlen. Wenn du statt "new Integer()" ein
"Integer.valueOf" benutzen würdest, würde es schon nicht mehr gehen.
Hm, könnte dir eine HashMap helfen, die ihre Werte per SoftReference
hält? Kann man ja auch auf WeakReference umbauen.
Habe ich mal irgendwo aufgeschnappt, etwas aufgehübscht und in meine
Toolbox genommen, sorry für die bescheidene Formatierung, aber ne IDE
kann das ja wieder grade rücken..
Gruß,
-Wanja-
/**
* A SoftHashMap is a {@link java.util.Map Map}-implementation that uses
{@link java.lang.ref.SoftReference SoftReferences} to
* reference objects, quite similar to a {@link java.util.WeakHashMap
WeakHashMap}.<BR>
* The purpose of this class is to hold objects, that may be discarded
in case the VM needs to free some Memory.<BR>
* However, this implementation uses a user-defined amount <code>n
</code> (where <code>n=100</code> is the default) of hard
* references to reference the <code>n</code> last requests. That means
that if you request the same object 100 times, when
* <code>n=100</code>, the same object will be the only one referenced
by hard references thereafter.
* @param <K> the key type
* @param <V> the value type
*/
public class SoftHashMap<K,V> extends AbstractMap<K,V> {
/** Defaults to 100. */
private static final int HARD_SIZE_DEFAULT =100;
/** The number of "hard" references to hold internally. */
private final int HARD_SIZE;
/** The internal HashMap that will hold the SoftReference. */
private final Map<K,SoftValue<K,V>> hashMap = new HashMap
<K,SoftValue<K,V>>();
/** The FIFO list of hard references, order of last access. */
private final LinkedList<V> hardCache = new LinkedList<V>();
/** Reference queue for cleared SoftReference objects. */
private final ReferenceQueue<V> queue = new ReferenceQueue<V>();
/**
* Creates a SoftHashMap.<BR>
* By default this SoftHashMap will hold a hard reference to 100
objects.
*/
public SoftHashMap() {
this(HARD_SIZE_DEFAULT);
}
/**
* Creates a SoftHashMap with the given number of hard references.
<BR>
* @param hardSize the numberof hard references in the map.
*/
public SoftHashMap(final int hardSize) {
HARD_SIZE = hardSize;
}
/**
* Gets the object maped to the given key.<BR>
* Since a SoftHashMap uses {@link SoftReference SoftReferences}
to access the objects, the objects put to this map may get
* garbage-collected when memory is needed.<BR>
* In case you request an Object that has been GarbageCollected,
this method will return null.
* @see java.util.Map#get(java.lang.Object)
* @param key the key to the requested object
* @return the object mapped to the given key or null if none
exists
*/
@Override
public V get(final Object key) {
V result = null;
// We get the SoftReference represented by that key
final SoftReference<V> softRef = hashMap.get(key);
if (softRef != null) {
// From the SoftReference we get the value, which
can be
// null if it was not in the map, or it was removed
in
// the processQueue() method defined below
result = softRef.get();
if (result == null) {
// If the value has been garbage collected,
remove the
// entry from the HashMap.
hashMap.remove(key);
} else {
// We now add this object to the beginning of
the hard
// reference queue. One reference can occur
more than
// once, because lookups of the FIFO queue
are slow, so
// we don't want to search through it each
time to remove
// duplicates.
hardCache.addFirst(result);
if (hardCache.size() > this.HARD_SIZE) {
// Remove the last entry if list
longer than HARD_SIZE
hardCache.removeLast();
}
}
}
return result;
}
/**
* Puts a key, value pair into the SoftHashMap.<BR>
* Since a SoftHashMap uses {@link SoftReference SoftReferences}
to access the objects, the objects put to this map may get
* garbage-collected when memory is needed.
* @param key the key to the object
* @param value the object mapped to the key
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
* (A <tt>null</tt> return can also indicate that the map
* previously associated <tt>null</tt> with <tt>key</tt>,
* if the implementation supports <tt>null</tt> values.)
*/
@Override
public V put(final K key, final V value) {
processQueue(); // throw out garbage collected values first
return hashMap.put(key, new SoftValue<K,V>(value, key,
queue)).get();
}
/**
* @see java.util.Map#remove(java.lang.Object)
* @param key key whose mapping is to be removed from the map
* @return the Object removed
*/
@Override
public V remove(final Object key) {
processQueue(); // throw out garbage collected values first
// searching through hard cache would take too long, the
object will be discarded after a few requests anyway
return hashMap.remove(key).get();
}
/**
* @see java.util.Map#clear()
*/
@Override
public void clear() {
hardCache.clear();
processQueue(); // throw out garbage collected values
hashMap.clear();
}
/**
* @see java.util.Map#size()
* @return the number of entries in the map
*/
@Override
public int size() {
processQueue(); // throw out garbage collected values first
return hashMap.size();
}
/**
* Returns a Set that contains all not garbage-collected entries
in this Map.<BR>
* Note that the Map.Entries in this set strongly reference their
values and that the returned set strongly references the Map.Entries it
contains.
* @see java.util.Map#entrySet()
* @return a set that contains all entries in this map
*/
@Override
public Set<Map.Entry<K,V>> entrySet() {
processQueue(); // throw out garbage collected values first
//build set
final Set<Map.Entry<K,V>> set = new HashSet<Map.Entry<K,V>>
(size());
for(final Map.Entry<K, SoftValue<K,V>> entry :
hashMap.entrySet()){
final V value = entry.getValue().get();
if(value !=null){
set.add(new Entry(entry.getKey(), value));
}
}
return set;
}
/**
* Goes through the ReferenceQueue and removes garbage collected
SoftValue objects from the HashMap by looking them up using
* the {@link SoftValue#key SoftValue.key}.
*/
private void processQueue() {
SoftValue<?,?> sv;
while ((sv = (SoftValue<?,?>)queue.poll()) != null) {
hashMap.remove(sv.key);
}
}
/**
* Implementation of the {@link Map.Entry Map.Entry<K,V>}-
interface.<BR>
* Note that objects of this class strongly reference their
values.
*/
protected final class Entry implements Map.Entry<K,V>, Cloneable {
private final K key;
private V value;
/**
* Constructs a new Entry with the given key and value.
* @param key the key to the Entry
* @param value the value of the Entry
*/
protected Entry(final K key, final V value){
this.key=key;
this.value=value;
}
/**
* Gets the key from this map-entry.
* @return the key object
* @see java.util.Map.Entry#getKey()
*/
public K getKey() {
return key;
}
/**
* Gets the value.
* @return the mapped value.
* @see java.util.Map.Entry#getValue()
*/
public V getValue() {
return value;
}
/**
* Sets a new value for the mapping.<BR>
* Setting a new Value to the entry, will remap this value
in the map, just like this code would do:<BR>
* <code>
* <pre>
* {@linkplain SoftHashMap} m;
* //...
* {@linkplain Map.Entry} entry;
* //..
* map.{@linkplain Map#put(Object, Object) put(}{@linkplain
Map.Entry#getKey() entry.getKey()},{@linkplain Map.Entry#getValue()
entry.getValue()});
* </pre>
* </code>
* @param value any Object extending V
* @return the previous value associated with <tt>key</tt>,
or
* <tt>null</tt> if the value has been
GarbageCollected
* (A <tt>null</tt> return can also indicate that
the map
* previously associated <tt>null</tt> with <tt>key
</tt>,
* if the implementation supports <tt>null</tt>
values.)
* @see java.util.Map.Entry#setValue(Object)
*/
public V setValue(final V value) {
final V old = SoftHashMap.this.put(key, value);
this.value = value;
return old;
}
/**
* Clones this instance of this class.
* @return a cloned instance of this class.
* @see java.lang.Object#clone()
*/
@Override
public Entry clone(){
return new Entry(key, value);
}
}
/**
* Subclass of SoftReference which contains not only the value but
also the key to make it easier to find the entry in the
* HashMap after it's been garbage collected.
* @param <KT> Key Type
* @param <VT> Value Type
*/
private static final class SoftValue<KT,VT> extends SoftReference<VT> {
private final KT key; // always make data member final
private SoftValue(final VT value, final KT key, final
ReferenceQueue<? super VT> q) {
super(value, q);
this.key = key;
}
}
}
Gruß,
-Wanja-
--
Ada Byron, die Lochkarten für Babbages "Difference Engine" vorbereitete,
gilt als die erste Programmiererin der Weltgeschichte. Sie hat auch das
Verhaltensmuster für alle nachfolgenden Programmierer vorgegeben: Sie
trank und schluckte Drogen.
.
- References:
- Symboltabelle mit WeakReferences? Wie?
- From: Stefan Matthias Aust
- Re: Symboltabelle mit WeakReferences? Wie?
- From: Wanja Gayk
- Re: Symboltabelle mit WeakReferences? Wie?
- From: Stefan Matthias Aust
- Symboltabelle mit WeakReferences? Wie?
- Prev by Date: Re: Parsen eines Datums
- Next by Date: Klassen (z.B. Treiber) suchen
- Previous by thread: Re: Symboltabelle mit WeakReferences? Wie?
- Next by thread: Welches System?
- Index(es):
Relevant Pages
|