package org.limewire.collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Provides a priority queue with bounded size in an
* <a href="http://en.wikipedia.org/wiki/AVL_tree">AVL tree</a>.
* <code>FixedsizePriorityQueue</code> guarantees the lowest priority element
* is ejected when exceeding capacity.
* <p>
* <code>FixedsizePriorityQueue</code> provides {@link #extractMax()} to extract
* the maximum element. <code>FixedsizePriorityQueue</code> requires an explicit
* {@link Comparator}; <code>FixedsizePriorityQueue</code> won't use the natural
* ordering of values.
* <p>
* Fetching the max element takes O(lg N) time, where N is the number of
* elements. Also, extracting and adding elements is O(lg N) time.
* <p>
* This class is not thread-safe.
<pre>
FixedsizePriorityQueue<String> fpq =
new FixedsizePriorityQueue<String>(Comparators.stringComparator(), 3);
fpq.insert("Abby");
fpq.insert("Bob");
fpq.insert("Chris");
System.out.println(fpq);
System.out.println("Inserting another String pushes out an element (" + fpq.insert("Dan") + ") since the max. size was reached.");
System.out.println(fpq);
System.out.println("Minimum element: " + fpq.getMin());
System.out.println("Maximum element: " + fpq.getMax());
fpq.extractMax();
System.out.println(fpq);
Output:
[Abby, Bob, Chris]
Inserting another String pushes out an element (Abby) since the max. size was reached.
[Bob, Chris, Dan]
Minimum element: Bob
Maximum element: Dan
[Bob, Chris]
</pre>
*/
public class FixedsizePriorityQueue<E> implements Iterable<E> {
/**
* The underlying data structure.
* INVARIANT: tree.size()<=capacity
* INVARIANT: all elements of tree instanceof Node
*/
private SortedList<E> tree;
/** The maximum number of elements to hold. */
private int capacity;
/**
* Creates a new FixedsizePriorityQueue that will hold at most
* <tt>capacity</tt> elements.
* @param comparator expresses priority. Note that
* comaparator.compareTo(a,b)==0 does not imply that a.equals(b).
* @param capacity the maximum number of elements
* @exception IllegalArgumentException capacity negative
*/
public FixedsizePriorityQueue(Comparator<? super E> comparator, int capacity)
throws IllegalArgumentException {
if (capacity<=0)
throw new IllegalArgumentException();
tree=new SortedList<E>(comparator);
this.capacity=capacity;
}
public void clear() {
tree.clear();
}
public boolean isFull() {
return size() >= capacity();
}
/**
* Adds x to this, possibly removing some lower priority entry if necessary
* to ensure this.size()<=this.capacity(). If this has capacity, x will be
* added even if already in this (possibly with a different priority).
*
* @param x the entry to add
* @return the element ejected, possibly x, or null if none
*/
public E insert(E x) {
if (!isFull()) {
//a) Size less than capacity. Just add x.
boolean added=tree.add(x);
assert added;
return null;
} else {
//Ensure size does not exceed capacity.
//Micro-optimizations are possible.
E smallest = tree.first();
if (tree.comparator().compare(x,smallest)>0) {
//b) x larger than smallest of this: remove smallest and add x
tree.remove(smallest);
boolean added=tree.add(x);
assert added;
return smallest;
} else {
//c) Otherwise do nothing.
return x;
}
}
}
public E extractMax() {
E e = getMax();
remove(e);
return e;
}
/**
* Returns the highest priority element of this.
* @exception NoSuchElementException this.size()==0
*/
public E getMax() throws NoSuchElementException {
return tree.last();
}
/**
* Returns the lowest priority element of this.
* @exception NoSuchElementException this.size()==0
*/
public E getMin() throws NoSuchElementException {
return tree.first();
}
/**
* Returns true if this contains o. Runs in O(N) time, where N is
* number of elements in this.
*
* @param o this contains a x s.t. o.equals(x). Note that
* priority is ignored in this operation.
*/
public boolean contains(E o) {
return tree.contains(o);
}
/**
* Removes the first occurrence of o.
*
* @return true this contained an x such that o.equals(x).
*/
public boolean remove(E o) {
return tree.remove(o);
}
/**
* Returns an iterator of the elements in this, from <b>worst to best</b>.
*/
public Iterator<E> iterator() {
return tree.iterator();
}
/**
* Returns the number of elements in this.
*/
public int size() {
return tree.size();
}
/**
* Returns the maximum number of elements this can hold.
* @return the value passed to this constructor
*/
public int capacity() {
return capacity;
}
@Override
public String toString() {
return tree.toString();
}
}