All Downloads are FREE. Search and download functionalities are using the official Maven repository.

uk.org.retep.util.collections.TimedHashMap Maven / Gradle / Ivy

There is a newer version: 10.6
Show newest version
/*
 * 

Copyright (c) 1998-2008, Peter T Mount
* All rights reserved.

* *

Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met:

* *
    *
  • Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer.
  • * *
  • Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution.
  • * *
  • Neither the name of the retep.org.uk nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission.
  • * *
* *

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/ package uk.org.retep.util.collections; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * * @author peter */ public class TimedHashMap extends HashMap implements TimedMap { static final long serialVersionUID = 6953795673173999149L; private Map> map; private long lifetime = 600000L; // 10 minutes /** Creates a new instance of TimedHashMap */ public TimedHashMap() { map = new HashMap>(); } public TimedHashMap( long lifetime ) { this(); setLifetime( lifetime ); } public void setLifetime( long millis ) { lifetime = millis; } public long getLifetime() { return lifetime; } public V get( Object key ) { synchronized( this ) { V ret = null; TimedHashMapEntry ce = map.get( key ); if( ce != null ) { long deathTime = ce.getCreated() + lifetime; if( deathTime > System.currentTimeMillis() ) { ret = ce.getObject(); } else { remove( key ); } } return ret; } } public V put( K key, V value ) { synchronized( this ) { V ret = null; TimedHashMapEntry ce = map.get( key ); if( ce == null ) { ce = map.put( key, new TimedHashMapEntry( value ) ); if( ce != null ) { ret = ce.getObject(); } } else { ret = ce.getObject(); ce.setObject( value ); } return ret; } } public Collection values() { return new CacheCollection( map.values() ); } /** * Usually objects are only removed from the cache when they are next * referenced. However, this method will remove all dead entries. This is * usually called from a house keeping thread. */ public void clearTombstones() { synchronized( this ) { Iterator it = keySet().iterator(); while( it.hasNext() ) { Object key = it.next(); TimedHashMapEntry ce = (TimedHashMapEntry) super.get( key ); if( ce != null ) { long deathTime = ce.getCreated() + lifetime; if( deathTime <= System.currentTimeMillis() ) { it.remove(); } } } } } /** * Removes all keys that begin with the given prefix */ public void clearPrefix( String prefix ) { synchronized( this ) { Iterator it = keySet().iterator(); while( it.hasNext() ) { Object key = it.next(); TimedHashMapEntry ce = (TimedHashMapEntry) super.get( key ); if( ce != null ) { if( key instanceof String && ((String) key).startsWith( prefix ) ) { it.remove(); } } } } } private class CacheIterator implements Iterator { private Iterator iterator; public CacheIterator( Collection> col ) { List l = new ArrayList(); for( TimedHashMapEntry e : col ) { l.add( e.getObject() ); } iterator = l.iterator(); } public CacheIterator( Iterator it ) { iterator = it; } /** * Returns true if the iteration has more elements. (In other * words, returns true if next would return an element * rather than throwing an exception.) * * @return true if the iterator has more elements. * */ public boolean hasNext() { return iterator.hasNext(); } /** Returns the next element in the iteration. * * @return the next element in the iteration. * @exception NoSuchElementException iteration has no more elements. * */ @SuppressWarnings( "unchecked" ) public V next() { V obj = iterator.next(); if( obj instanceof TimedHashMapEntry ) { obj = ((TimedHashMapEntry) obj).getObject(); } return obj; } /** * Removes from the underlying collection the last element returned by the * iterator (optional operation). This method can be called only once per * call to next. The behavior of an iterator is unspecified if * the underlying collection is modified while the iteration is in * progress in any way other than by calling this method. * * @exception UnsupportedOperationException if the remove * operation is not supported by this Iterator. * * @exception IllegalStateException if the next method has not * yet been called, or the remove method has already * been called after the last call to the next * method. * */ public void remove() { iterator.remove(); } } private class CacheCollection implements Collection { private Collection> col; public CacheCollection( Collection> aCollection ) { col = aCollection; } /** Ensures that this collection contains the specified element (optional * operation). Returns true if this collection changed as a * result of the call. (Returns false if this collection does * not permit duplicates and already contains the specified element.)

* * Collections that support this operation may place limitations on what * elements may be added to this collection. In particular, some * collections will refuse to add null elements, and others will * impose restrictions on the type of elements that may be added. * Collection classes should clearly specify in their documentation any * restrictions on what elements may be added.

* * If a collection refuses to add a particular element for any reason * other than that it already contains the element, it must throw * an exception (rather than returning false). This preserves * the invariant that a collection always contains the specified element * after this call returns. * * @param o element whose presence in this collection is to be ensured. * @return true if this collection changed as a result of the * call * * @throws UnsupportedOperationException add is not supported by * this collection. * @throws ClassCastException class of the specified element prevents it * from being added to this collection. * @throws NullPointerException if the specified element is null and this * collection does not support null elements. * @throws IllegalArgumentException some aspect of this element prevents * it from being added to this collection. * */ public boolean add( V o ) { return col.add( new TimedHashMapEntry( o ) ); } /** Adds all of the elements in the specified collection to this collection * (optional operation). The behavior of this operation is undefined if * the specified collection is modified while the operation is in progress. * (This implies that the behavior of this call is undefined if the * specified collection is this collection, and this collection is * nonempty.) * * @param c elements to be inserted into this collection. * @return true if this collection changed as a result of the * call * * @throws UnsupportedOperationException if this collection does not * support the addAll method. * @throws ClassCastException if the class of an element of the specified * collection prevents it from being added to this collection. * @throws NullPointerException if the specified collection contains one * or more null elements and this collection does not support null * elements, or if the specified collection is null. * @throws IllegalArgumentException some aspect of an element of the * specified collection prevents it from being added to this * collection. * @see #add(Object) * */ @SuppressWarnings( "unchecked" ) public boolean addAll( Collection c ) { Iterator it = c.iterator(); boolean changed = false; while( it.hasNext() ) { Object obj = it.next(); if( obj instanceof TimedHashMapEntry ) { changed |= col.add( (TimedHashMapEntry) obj ); } else { changed |= col.add( new TimedHashMapEntry( (V) obj ) ); } } return changed; } /** Removes all of the elements from this collection (optional operation). * This collection will be empty after this method returns unless it * throws an exception. * * @throws UnsupportedOperationException if the clear method is * not supported by this collection. * */ public void clear() { col.clear(); } /** Returns true if this collection contains the specified * element. More formally, returns true if and only if this * collection contains at least one element e such that * (o==null ? e==null : o.equals(e)). * * @param o element whose presence in this collection is to be tested. * @return true if this collection contains the specified * element * @throws ClassCastException if the type of the specified element * is incompatible with this collection (optional). * @throws NullPointerException if the specified element is null and this * collection does not support null elements (optional). * */ public boolean contains( Object o ) { boolean notFound = true; Iterator it = col.iterator(); while( notFound && it.hasNext() ) { TimedHashMapEntry ce = (TimedHashMapEntry) it.next(); notFound = !(ce.getObject().equals( o )); } return !notFound; } /** Returns true if this collection contains all of the elements * in the specified collection. * * @param c collection to be checked for containment in this collection. * @return true if this collection contains all of the elements * in the specified collection * @throws ClassCastException if the types of one or more elements * in the specified collection are incompatible with this * collection (optional). * @throws NullPointerException if the specified collection contains one * or more null elements and this collection does not support null * elements (optional). * @throws NullPointerException if the specified collection is * null. * @see #contains(Object) * */ public boolean containsAll( Collection c ) { boolean found = true; Iterator it = c.iterator(); while( found && it.hasNext() ) { found = contains( it.next() ); } return found; } /** Returns true if this collection contains no elements. * * @return true if this collection contains no elements * */ public boolean isEmpty() { return col.isEmpty(); } /** Returns an iterator over the elements in this collection. There are no * guarantees concerning the order in which the elements are returned * (unless this collection is an instance of some class that provides a * guarantee). * * @return an Iterator over the elements in this collection * */ public Iterator iterator() { return new CacheIterator( col ); } /** Removes a single instance of the specified element from this * collection, if it is present (optional operation). More formally, * removes an element e such that (o==null ? e==null : * o.equals(e)), if this collection contains one or more such * elements. Returns true if this collection contained the specified * element (or equivalently, if this collection changed as a result of the * call). * * @param o element to be removed from this collection, if present. * @return true if this collection changed as a result of the * call * * @throws ClassCastException if the type of the specified element * is incompatible with this collection (optional). * @throws NullPointerException if the specified element is null and this * collection does not support null elements (optional). * @throws UnsupportedOperationException remove is not supported by this * collection. * */ public boolean remove( Object o ) { boolean run = true; Iterator it = col.iterator(); while( run && it.hasNext() ) { if( o.equals( it.next() ) ) { it.remove(); run = false; } } return !run; } /** * Removes all this collection's elements that are also contained in the * specified collection (optional operation). After this call returns, * this collection will contain no elements in common with the specified * collection. * * @param c elements to be removed from this collection. * @return true if this collection changed as a result of the * call * * @throws UnsupportedOperationException if the removeAll method * is not supported by this collection. * @throws ClassCastException if the types of one or more elements * in this collection are incompatible with the specified * collection (optional). * @throws NullPointerException if this collection contains one or more * null elements and the specified collection does not support * null elements (optional). * @throws NullPointerException if the specified collection is * null. * @see #remove(Object) * @see #contains(Object) * */ public boolean removeAll( Collection c ) { boolean changed = false; Iterator it = c.iterator(); while( it.hasNext() ) { Object o = it.next(); boolean removed = false; do { removed = remove( o ); changed |= removed; } while( removed ); } return changed; } /** Retains only the elements in this collection that are contained in the * specified collection (optional operation). In other words, removes from * this collection all of its elements that are not contained in the * specified collection. * * @param c elements to be retained in this collection. * @return true if this collection changed as a result of the * call * * @throws UnsupportedOperationException if the retainAll method * is not supported by this Collection. * @throws ClassCastException if the types of one or more elements * in this collection are incompatible with the specified * collection (optional). * @throws NullPointerException if this collection contains one or more * null elements and the specified collection does not support null * elements (optional). * @throws NullPointerException if the specified collection is * null. * @see #remove(Object) * @see #contains(Object) * */ public boolean retainAll( Collection c ) { // todo return false; } /** Returns the number of elements in this collection. If this collection * contains more than Integer.MAX_VALUE elements, returns * Integer.MAX_VALUE. * * @return the number of elements in this collection * */ public int size() { return col.size(); } /** Returns an array containing all of the elements in this collection. If * the collection makes any guarantees as to what order its elements are * returned by its iterator, this method must return the elements in the * same order.

* * The returned array will be "safe" in that no references to it are * maintained by this collection. (In other words, this method must * allocate a new array even if this collection is backed by an array). * The caller is thus free to modify the returned array.

* * This method acts as bridge between array-based and collection-based * APIs. * * @return an array containing all of the elements in this collection * */ public Object[] toArray() { Object ary[] = new Object[ size() ]; Iterator it = col.iterator(); for( int i = 0; it.hasNext(); i++ ) { ary[i] = it.next(); } return ary; } /** Returns an array containing all of the elements in this collection; * the runtime type of the returned array is that of the specified array. * If the collection fits in the specified array, it is returned therein. * Otherwise, a new array is allocated with the runtime type of the * specified array and the size of this collection.

* * If this collection fits in the specified array with room to spare * (i.e., the array has more elements than this collection), the element * in the array immediately following the end of the collection is set to * null. This is useful in determining the length of this * collection only if the caller knows that this collection does * not contain any null elements.)

* * If this collection makes any guarantees as to what order its elements * are returned by its iterator, this method must return the elements in * the same order.

* * Like the toArray method, this method acts as bridge between * array-based and collection-based APIs. Further, this method allows * precise control over the runtime type of the output array, and may, * under certain circumstances, be used to save allocation costs

* * Suppose l is a List known to contain only strings. * The following code can be used to dump the list into a newly allocated * array of String: * *

         *     String[] x = (String[]) v.toArray(new String[0]);
         * 

* * Note that toArray(new Object[0]) is identical in function to * toArray(). * * @param a the array into which the elements of this collection are to be * stored, if it is big enough; otherwise, a new array of the same * runtime type is allocated for this purpose. * @return an array containing the elements of this collection * * @throws ArrayStoreException the runtime type of the specified array is * not a supertype of the runtime type of every element in this * collection. * @throws NullPointerException if the specified array is null. * */ public T[] toArray( T[] a ) { // todo return a; } } private class TimedHashMapEntry { /** Holds value of property object. */ private V object; private long created; public TimedHashMapEntry() { this( null ); } public TimedHashMapEntry( V aObject ) { setObject( aObject ); } /** Getter for property object. * @return Value of property object. * */ public V getObject() { return this.object; } /** Setter for property object. * @param object New value of property object. * */ public void setObject( V object ) { this.object = object; setCreated( System.currentTimeMillis() ); } /** Getter for property created. * @return Value of property created. * */ public long getCreated() { return created; } /** Setter for property created. * @param created New value of property created. * */ public void setCreated( long aCreated ) { created = aCreated; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy