package org.limewire.collection; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.ConcurrentModificationException; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.Set; /** * * A hash-based <code>Set</code> ordered with the last added element is the * first item in the list. * <pre> LIFOSet<String> s = new LIFOSet<String>(1); s.add("Abby"); s.add("Bob"); s.add("Chris"); s.add("Dan"); s.add("Eric"); s.add("Fred"); System.out.println(s); Output: [Fred, Eric, Dan, Chris, Bob, Abby] </pre> */ public class LIFOSet<E> implements Set<E>{ private final Set<E> set; private final List<E> list; public LIFOSet() { this(50, 0.75F); } public LIFOSet(int initialCapacity){ this(initialCapacity, 0.75F); } public LIFOSet(int initialCapacity, float loadFactor){ set = new HashSet<E>(initialCapacity, loadFactor); list = new ArrayList<E>(initialCapacity); } /** * Adds the given element to the head of the set. */ public boolean add(E o) { if(set.add(o)) { list.add(o); return true; } list.remove(o); list.add(o); return false; } public boolean addAll(Collection<? extends E> c) { boolean ret = false; for(E e : c) { ret |= add(e); } return ret; } public void clear() { set.clear(); list.clear(); } public boolean contains(Object o) { return set.contains(o); } public boolean containsAll(Collection<?> c) { return set.containsAll(c); } public boolean isEmpty() { return set.isEmpty(); } public Iterator<E> iterator() { return new LIFOSetIterator(); } public boolean remove(Object o) { if (set.remove(o)) { list.remove(o); return true; } return false; } /** * Removes the first (eldest) element from the ordered set * * @return true if the set was changed */ protected boolean removeEldest() { if (list.isEmpty()) { return false; } return remove(0); } /** * Removes the last (newest) element from the ordered set * * @return true if the set was changed */ protected boolean removeNewest() { if(list.isEmpty()) { return false; } return remove(list.size()-1); } /** * Removes the element at the given index from the ordered Set */ protected boolean remove(int index) { return set.remove(list.remove(index)); } public boolean removeAll(Collection<?> c) { list.removeAll(c); return set.removeAll(c); } public boolean retainAll(Collection<?> c) { list.retainAll(c); return set.retainAll(c); } public int size() { return set.size(); } public Object[] toArray() { List<E> reverse = new ArrayList<E>(list); Collections.reverse(reverse); return reverse.toArray(); } @SuppressWarnings({"SuspiciousToArrayCall"}) public <T> T[] toArray(T[] a) { List<E> reverse = new ArrayList<E>(list); Collections.reverse(reverse); return reverse.toArray(a); } @Override public String toString() { List<E> reverse = new ArrayList<E>(list); Collections.reverse(reverse); return reverse.toString(); } private class LIFOSetIterator implements Iterator<E> { private E current; private int index = 0; public LIFOSetIterator() { index = list.size() - 1; } public boolean hasNext() { return index >= 0; } public E next() { if(index < 0) { throw new NoSuchElementException(); } current = list.get(index); --index; return current; } public void remove() { if(index == (list.size() - 1)) { throw new IllegalStateException(); } set.remove(current); E removed = list.remove(index + 1); if(removed != current) { throw new ConcurrentModificationException(); } current=null; } } }