javassist.scopedpool.SoftValueHashMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javassist Show documentation
Show all versions of javassist Show documentation
Javassist (JAVA programming ASSISTant) makes Java bytecode manipulation
simple. It is a class library for editing bytecodes in Java.
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package javassist.scopedpool;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* This Map will remove entries when the value in the map has been cleaned from
* garbage collection
*
* @version $Revision: 1.4 $
* @author Bill Burke
*/
public class SoftValueHashMap implements Map {
private static class SoftValueRef extends SoftReference {
public K key;
private SoftValueRef(K key, V val, ReferenceQueue q) {
super(val, q);
this.key = key;
}
private static SoftValueRef create(
K key, V val, ReferenceQueue q) {
if (val == null)
return null;
else
return new SoftValueRef(key, val, q);
}
}
/**
* Returns a set of the mappings contained in this hash table.
*/
@Override
public Set> entrySet() {
processQueue();
Set> ret = new HashSet>();
for (Entry> e:hash.entrySet())
ret.add(new SimpleImmutableEntry (
e.getKey(), e.getValue().get()));
return ret;
}
/* Hash table mapping WeakKeys to values */
private Map> hash;
/* Reference queue for cleared WeakKeys */
private ReferenceQueue queue = new ReferenceQueue();
/*
* Remove all invalidated entries from the map, that is, remove all entries
* whose values have been discarded.
*/
private void processQueue() {
Object ref;
if (!hash.isEmpty())
while ((ref = queue.poll()) != null)
if (ref instanceof SoftValueRef) {
@SuppressWarnings("rawtypes")
SoftValueRef que =(SoftValueRef) ref;
if (ref == hash.get(que.key))
// only remove if it is the *exact* same SoftValueRef
hash.remove(que.key);
}
}
/* -- Constructors -- */
/**
* Constructs a new, empty WeakHashMap
with the given initial
* capacity and the given load factor.
*
* @param initialCapacity
* The initial capacity of the WeakHashMap
*
* @param loadFactor
* The load factor of the WeakHashMap
*
* @throws IllegalArgumentException
* If the initial capacity is less than zero, or if the load
* factor is nonpositive
*/
public SoftValueHashMap(int initialCapacity, float loadFactor) {
hash = new ConcurrentHashMap>(initialCapacity, loadFactor);
}
/**
* Constructs a new, empty WeakHashMap
with the given initial
* capacity and the default load factor, which is 0.75
.
*
* @param initialCapacity
* The initial capacity of the WeakHashMap
*
* @throws IllegalArgumentException
* If the initial capacity is less than zero
*/
public SoftValueHashMap(int initialCapacity) {
hash = new ConcurrentHashMap>(initialCapacity);
}
/**
* Constructs a new, empty WeakHashMap
with the default
* initial capacity and the default load factor, which is 0.75
.
*/
public SoftValueHashMap() {
hash = new ConcurrentHashMap>();
}
/**
* Constructs a new WeakHashMap
with the same mappings as the
* specified Map
. The WeakHashMap
is created with
* an initial capacity of twice the number of mappings in the specified map
* or 11 (whichever is greater), and a default load factor, which is
* 0.75
.
*
* @param t the map whose mappings are to be placed in this map.
*/
public SoftValueHashMap(Map t) {
this(Math.max(2 * t.size(), 11), 0.75f);
putAll(t);
}
/* -- Simple queries -- */
/**
* Returns the number of key-value mappings in this map. Note:
* In contrast with most implementations of the
* Map
interface, the time required by this operation is
* linear in the size of the map.
*/
@Override
public int size() {
processQueue();
return hash.size();
}
/**
* Returns true
if this map contains no key-value mappings.
*/
@Override
public boolean isEmpty() {
processQueue();
return hash.isEmpty();
}
/**
* Returns true
if this map contains a mapping for the
* specified key.
*
* @param key
* The key whose presence in this map is to be tested.
*/
@Override
public boolean containsKey(Object key) {
processQueue();
return hash.containsKey(key);
}
/* -- Lookup and modification operations -- */
/**
* Returns the value to which this map maps the specified key
.
* If this map does not contain a value for this key, then return
* null
.
*
* @param key
* The key whose associated value, if any, is to be returned.
*/
@Override
public V get(Object key) {
processQueue();
return valueOrNull(hash.get(key));
}
/**
* Updates this map so that the given key
maps to the given
* value
. If the map previously contained a mapping for
* key
then that mapping is replaced and the previous value
* is returned.
*
* @param key
* The key that is to be mapped to the given value
* @param value
* The value to which the given key
is to be
* mapped
*
* @return The previous value to which this key was mapped, or
* null
if if there was no mapping for the key
*/
@Override
public V put(K key, V value) {
processQueue();
return valueOrNull(hash.put(key, SoftValueRef.create(key, value, queue)));
}
/**
* Removes the mapping for the given key
from this map, if
* present.
*
* @param key
* The key whose mapping is to be removed.
*
* @return The value to which this key was mapped, or null
if
* there was no mapping for the key.
*/
@Override
public V remove(Object key) {
processQueue();
return valueOrNull(hash.remove(key));
}
/**
* Removes all mappings from this map.
*/
@Override
public void clear() {
processQueue();
hash.clear();
}
/*
* Check whether the supplied value exists.
* @param Object the value to compare.
* @return true if it was found or null.
*/
@Override
public boolean containsValue(Object arg0) {
processQueue();
if (null == arg0)
return false;
for (SoftValueRef e:hash.values())
if (null != e && arg0.equals(e.get()))
return true;
return false;
}
/* {@inheritDoc} */
@Override
public Set keySet() {
processQueue();
return hash.keySet();
}
/* {@inheritDoc} */
@Override
public void putAll(Map extends K,? extends V> arg0) {
processQueue();
for (K key:arg0.keySet())
put(key, arg0.get(key));
}
/* {@inheritDoc} */
@Override
public Collection values() {
processQueue();
List ret = new ArrayList();
for (SoftValueRef e:hash.values())
ret.add(e.get());
return ret;
}
private V valueOrNull(SoftValueRef rtn) {
if (null == rtn)
return null;
return rtn.get();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy