package org.limewire.collection; import java.util.AbstractSet; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.Set; /** * Stores a fixed size of elements as a <code>Set</code> and removes elements * when that size is reached. <code>FixedsizeForgetfulHashSet</code> is a * <code>Set</code> version of {@link FixedsizeForgetfulHashMap}. Like * <code>ForgetfulHashMap</code>, values are "forgotten" using a FIFO replacement * policy. * <p> * <code>FixedsizeForgetfulHashSet</code> works in constant time. * <pre> FixedsizeForgetfulHashSet<String> ffhs = new FixedsizeForgetfulHashSet<String>(4); ffhs.add("Abby"); System.out.println(ffhs); if(!ffhs.add("Abby")) System.out.println("The set already contained that item; Set contents: " + ffhs); ffhs.add("Bob"); ffhs.add("Bob"); ffhs.add("Chris"); ffhs.add("Dan"); System.out.println(ffhs); ffhs.add("Eric"); System.out.println(ffhs); Output: [Abby] The set already contained that item; Set contents: [Abby] [Abby, Bob, Chris, Dan] [Bob, Chris, Dan, Eric] </pre> * */ public class FixedsizeForgetfulHashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable { /** * Backing map which the set delegates. */ private transient FixedsizeForgetfulHashMap<E,Object> map; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); /** * Constructs a new, empty set. */ public FixedsizeForgetfulHashSet(int size) { map = new FixedsizeForgetfulHashMap<E,Object>(size); } /** * Constructs a new, empty set, using the given initialCapacity. */ public FixedsizeForgetfulHashSet(int size, int initialCapacity) { map = new FixedsizeForgetfulHashMap<E,Object>(size, initialCapacity); } /** * Constructs a new, empty set, using the given initialCapacity & loadFactor. */ public FixedsizeForgetfulHashSet(int size, int initialCapacity, float loadFactor) { map = new FixedsizeForgetfulHashMap<E,Object>(size, initialCapacity, loadFactor); } /** * Tests if the set is full. * * @return true, if the set is full (ie if adding any other entry will * lead to removal of some other entry to maintain the fixed-size property * of the set). Returns false, otherwise */ public boolean isFull() { return map.isFull(); } /** * Removes the least recently used entry from the set * @return The least recently used value from the set. * @modifies this. */ public E removeLRUEntry() { if(isEmpty()) return null; Iterator<E> i = iterator(); E value = i.next(); i.remove(); return value; } /** * Returns an iterator over the elements in this set. The elements * are returned in no particular order. * * @return an Iterator over the elements in this set. * @see ConcurrentModificationException */ @Override public Iterator<E> iterator() { return map.keySet().iterator(); } /** * @return the number of elements in this set (its cardinality). */ @Override public int size() { return map.size(); } /** * @return <tt>true</tt> if this set contains no elements. */ @Override public boolean isEmpty() { return map.isEmpty(); } /** * Returns <tt>true</tt> if this set contains the specified element. * * @param o element whose presence in this set is to be tested. * @return <tt>true</tt> if this set contains the specified element. */ @SuppressWarnings({"SuspiciousMethodCalls"}) @Override public boolean contains(Object o) { return map.containsKey(o); } /** * Adds the specified element to this set if it is not already * present. * * @param o element to be added to this set. * @return <tt>true</tt> if the set did not already contain the specified * element. */ @Override public boolean add(E o) { return map.put(o, PRESENT)==null; } /** * Removes the specified element from this set if it is present. * * @param o object to be removed from this set, if present. * @return <tt>true</tt> if the set contained the specified element. */ @Override public boolean remove(Object o) { return map.remove(o)==PRESENT; } /** * Removes all of the elements from this set. */ @Override public void clear() { map.clear(); } /** * Returns a shallow copy of this <tt>FixedsizeForgetfulHashSet</tt> instance: the elements * themselves are not cloned. * * @return a shallow copy of this set. */ @Override @SuppressWarnings("unchecked") public FixedsizeForgetfulHashSet<E> clone() throws CloneNotSupportedException { try { FixedsizeForgetfulHashSet<E> newSet = (FixedsizeForgetfulHashSet<E>)super.clone(); newSet.map = map.clone(); return newSet; } catch (CloneNotSupportedException e) { throw new InternalError(); } } }