package com.github.davidmoten.rtree.internal.util; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import com.github.davidmoten.guavamini.Preconditions; public final class BoundedPriorityQueue<T> { private final PriorityQueue<T> queue; /* backing data structure */ private final Comparator<? super T> comparator; private final int maxSize; /** * Constructs a {@link BoundedPriorityQueue} with the specified * {@code maxSize} and {@code comparator}. * * @param maxSize * - The maximum size the queue can reach, must be a positive * integer. * @param comparator * - The comparator to be used to compare the elements in the * queue, must be non-null. */ public BoundedPriorityQueue(final int maxSize, final Comparator<? super T> comparator) { Preconditions.checkArgument(maxSize > 0, "maxSize must be > 0"); Preconditions.checkNotNull(comparator, "comparator cannot be null"); this.queue = new PriorityQueue<T>(reverse(comparator)); this.comparator = comparator; this.maxSize = maxSize; } private static <T> Comparator<T> reverse(final Comparator<T> comparator) { return new Comparator<T>() { @Override public int compare(T o1, T o2) { return comparator.compare(o2, o1); } }; } public static <T> BoundedPriorityQueue<T> create(final int maxSize, final Comparator<? super T> comparator) { return new BoundedPriorityQueue<T>(maxSize, comparator); } /** * Adds an element to the queue. If the queue contains {@code maxSize} * elements, {@code e} will be compared to the lowest element in the queue * using {@code comparator}. If {@code e} is greater than or equal to the * lowest element, that element will be removed and {@code e} will be added * instead. Otherwise, the queue will not be modified and {@code e} will not * be added. * * @param t * - Element to be added, must be non-null. */ public void add(final T t) { if (t == null) { throw new NullPointerException("cannot add null to the queue"); } if (queue.size() >= maxSize) { final T maxElement = queue.peek(); if (comparator.compare(maxElement, t) < 1) { return; } else { queue.poll(); } } queue.add(t); } /** * @return Returns a view of the queue as a * {@link Collections#unmodifiableList(java.util.List)} * unmodifiableList sorted in reverse order. */ public List<T> asList() { return Collections.unmodifiableList(new ArrayList<T>(queue)); } public List<T> asOrderedList() { List<T> list = new ArrayList<T>(queue); Collections.sort(list, comparator); return list; } }