package org.limewire.collection; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; /** * Provides a fixed size {@link HashSet} with index access. The replacement * policy is FIFO (First in, First out) and the iteration order is from newest * to oldest. * <p> * Adding an existing element resets the FIFO order; the newly added element is * now the "last in" element. * <p> * <code>FixedSizeArrayHashSet</code> does not support the null element. * <pre> FixedSizeArrayHashSet<String> fsah = new FixedSizeArrayHashSet<String>(4); fsah.add("Abby"); fsah.add("Bob"); fsah.add("Chris"); fsah.add("Dan"); fsah.add("Eric"); fsah.add("Fred"); System.out.println(fsah); if(!fsah.add("Chris")) System.out.println("Tried to add Chris again, but it already exists in the collection (though Chris was put to the first item)."); System.out.println(fsah); System.out.println("Index access: " + fsah.get(0)); fsah.remove("Chris"); System.out.println(fsah); Output: [Fred, Eric, Dan, Chris] Tried to add Chris again, but it already exists in the collection (though Chris was put to the first item). [Chris, Fred, Eric, Dan] Index access: Chris [Fred, Eric, Dan] </pre> */ public class FixedSizeArrayHashSet<E> extends HashSet<E> implements RandomAccessCollection<E> { private transient FixedSizeArrayHashMap<E,Object> map; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); /** * creates a FixedSizeArrayHashSet with the specified maximum capacity. */ public FixedSizeArrayHashSet(int maxCapacity) { map = new FixedSizeArrayHashMap<E, Object>(maxCapacity); } /** * Creates a <code>FixedSizeArrayHashSet</code> with maximum capacity the * size of the provided collection and adds all the elements of that * collection. */ public FixedSizeArrayHashSet(Collection<? extends E> c) { this(c.size()); addAll(c); } /** * Creates a <code>FixedSizeArrayHashSet</code> with the provided maximum capacity and * adds elements from the provided collection. If the capacity is less than * the size of the collection, elements will get ejected with FIFO policy. */ public FixedSizeArrayHashSet(int maxCapacity, Collection<? extends E> c) { this(maxCapacity); addAll(c); } public FixedSizeArrayHashSet(int maxCapacity, int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); map = new FixedSizeArrayHashMap<E, Object>(maxCapacity); } public FixedSizeArrayHashSet(int maxCapacity, int initialCapacity) { super(initialCapacity); map = new FixedSizeArrayHashMap<E, Object>(maxCapacity); } @Override public Iterator<E> iterator() { return map.keySet().iterator(); } @Override public int size() { return map.size(); } @Override public boolean isEmpty() { return map.isEmpty(); } @SuppressWarnings({"SuspiciousMethodCalls"}) @Override public boolean contains(Object o) { return map.containsKey(o); } @Override public boolean add(E o) { return map.put(o, PRESENT)==null; } @Override public boolean remove(Object o) { return map.remove(o)==PRESENT; } @Override public void clear() { map.clear(); } @Override @SuppressWarnings("unchecked") public Object clone() { FixedSizeArrayHashSet<E> newSet = (FixedSizeArrayHashSet<E>) super.clone(); newSet.map = (FixedSizeArrayHashMap<E, Object>) map.clone(); return newSet; } public E get(int i) { return map.getKeyAt(i); } }