Class MinMaxPriorityQueue<E>
- java.lang.Object
-
- java.util.AbstractCollection<E>
-
- java.util.AbstractQueue<E>
-
- com.google.common.collect.MinMaxPriorityQueue<E>
-
- All Implemented Interfaces:
java.lang.Iterable<E>
,java.util.Collection<E>
,java.util.Queue<E>
public final class MinMaxPriorityQueue<E> extends java.util.AbstractQueue<E>
A double-ended priority queue, which provides constant-time access to both its least element and its greatest element, as determined by the queue's specified comparator. If no comparator is given at creation time, the natural order of elements is used. If no maximum size is given at creation time, the queue is unbounded.Usage example:
MinMaxPriorityQueue<User> users = MinMaxPriorityQueue.orderedBy(userComparator) .maximumSize(1000) .create();
As a
Queue
it functions exactly as aPriorityQueue
: its head element -- the implicit target of the methodspeek()
,poll()
andAbstractQueue.remove()
-- is defined as the least element in the queue according to the queue's comparator. But unlike a regular priority queue, the methodspeekLast()
,pollLast()
andremoveLast()
are also provided, to act on the greatest element in the queue instead.A min-max priority queue can be configured with a maximum size. If so, each time the size of the queue exceeds that value, the queue automatically removes its greatest element according to its comparator (which might be the element that was just added). This is different from conventional bounded queues, which either block or reject new elements when full.
This implementation is based on the min-max heap developed by Atkinson, et al. Unlike many other double-ended priority queues, it stores elements in a single array, as compact as the traditional heap data structure used in
PriorityQueue
.This class is not thread-safe, and does not accept null elements.
Performance notes:
- If you only access one end of the queue, and do use a maximum size, this class will perform
significantly worse than a
PriorityQueue
with manual eviction above the maximum size. In many casesOrdering.leastOf(java.lang.Iterable<E>, int)
may work for your use case with significantly improved (and asymptotically superior) performance. - The retrieval operations
peek()
,peekFirst()
,peekLast()
,AbstractQueue.element()
, andsize
are constant-time. - The enqueuing and dequeuing operations (
offer(E)
,add(E)
, and all the forms ofpoll()
andAbstractQueue.remove()
) run inO(log n) time
. - The
AbstractCollection.remove(Object)
andAbstractCollection.contains(java.lang.Object)
operations require linear (O(n)
) time. - If you only access one end of the queue, and don't use a maximum size, this class is
functionally equivalent to
PriorityQueue
, but significantly slower.
- Since:
- 8.0
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
MinMaxPriorityQueue.Builder<B>
The builder class used in creation of min-max priority queues.private class
MinMaxPriorityQueue.Heap
Each instance of MinMaxPriortyQueue encapsulates two instances of Heap: a min-heap and a max-heap.(package private) static class
MinMaxPriorityQueue.MoveDesc<E>
private class
MinMaxPriorityQueue.QueueIterator
Iterates the elements of the queue in no particular order.
-
Field Summary
Fields Modifier and Type Field Description private static int
DEFAULT_CAPACITY
private static int
EVEN_POWERS_OF_TWO
private MinMaxPriorityQueue.Heap
maxHeap
(package private) int
maximumSize
private MinMaxPriorityQueue.Heap
minHeap
private int
modCount
private static int
ODD_POWERS_OF_TWO
private java.lang.Object[]
queue
private int
size
-
Constructor Summary
Constructors Modifier Constructor Description private
MinMaxPriorityQueue(MinMaxPriorityQueue.Builder<? super E> builder, int queueSize)
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description boolean
add(E element)
Adds the given element to this queue.boolean
addAll(java.util.Collection<? extends E> newElements)
private int
calculateNewCapacity()
Returns ~2x the old capacity if small; ~1.5x otherwise.(package private) int
capacity()
private static int
capAtMaximumSize(int queueSize, int maximumSize)
There's no reason for the queueSize to ever be more than maxSize + 1void
clear()
java.util.Comparator<? super E>
comparator()
Returns the comparator used to order the elements in this queue.static <E extends java.lang.Comparable<E>>
MinMaxPriorityQueue<E>create()
Creates a new min-max priority queue with default settings: natural order, no maximum size, no initial contents, and an initial expected size of 11.static <E extends java.lang.Comparable<E>>
MinMaxPriorityQueue<E>create(java.lang.Iterable<? extends E> initialContents)
Creates a new min-max priority queue using natural order, no maximum size, and initially containing the given elements.(package private) E
elementData(int index)
static MinMaxPriorityQueue.Builder<java.lang.Comparable>
expectedSize(int expectedSize)
Creates and returns a new builder, configured to buildMinMaxPriorityQueue
instances sized appropriately to holdexpectedSize
elements.private MinMaxPriorityQueue.MoveDesc<E>
fillHole(int index, E toTrickle)
private int
getMaxElementIndex()
Returns the index of the max element.private void
growIfNeeded()
private MinMaxPriorityQueue.Heap
heapForIndex(int i)
(package private) static int
initialQueueSize(int configuredExpectedSize, int maximumSize, java.lang.Iterable<?> initialContents)
(package private) static boolean
isEvenLevel(int index)
(package private) boolean
isIntact()
Returnstrue
if the MinMax heap structure holds.java.util.Iterator<E>
iterator()
Returns an iterator over the elements contained in this collection, in no particular order.static MinMaxPriorityQueue.Builder<java.lang.Comparable>
maximumSize(int maximumSize)
Creates and returns a new builder, configured to buildMinMaxPriorityQueue
instances that are limited tomaximumSize
elements.boolean
offer(E element)
Adds the given element to this queue.static <B> MinMaxPriorityQueue.Builder<B>
orderedBy(java.util.Comparator<B> comparator)
Creates and returns a new builder, configured to buildMinMaxPriorityQueue
instances that usecomparator
to determine the least and greatest elements.E
peek()
E
peekFirst()
Retrieves, but does not remove, the least element of this queue, or returnsnull
if the queue is empty.E
peekLast()
Retrieves, but does not remove, the greatest element of this queue, or returnsnull
if the queue is empty.E
poll()
E
pollFirst()
Removes and returns the least element of this queue, or returnsnull
if the queue is empty.E
pollLast()
Removes and returns the greatest element of this queue, or returnsnull
if the queue is empty.private E
removeAndGet(int index)
Removes and returns the value atindex
.(package private) MinMaxPriorityQueue.MoveDesc<E>
removeAt(int index)
Removes the element at positionindex
.E
removeFirst()
Removes and returns the least element of this queue.E
removeLast()
Removes and returns the greatest element of this queue.int
size()
java.lang.Object[]
toArray()
-
Methods inherited from class java.util.AbstractCollection
contains, containsAll, isEmpty, remove, removeAll, retainAll, toArray, toString
-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
-
-
-
-
Field Detail
-
minHeap
private final MinMaxPriorityQueue.Heap minHeap
-
maxHeap
private final MinMaxPriorityQueue.Heap maxHeap
-
maximumSize
final int maximumSize
-
queue
private java.lang.Object[] queue
-
size
private int size
-
modCount
private int modCount
-
EVEN_POWERS_OF_TWO
private static final int EVEN_POWERS_OF_TWO
- See Also:
- Constant Field Values
-
ODD_POWERS_OF_TWO
private static final int ODD_POWERS_OF_TWO
- See Also:
- Constant Field Values
-
DEFAULT_CAPACITY
private static final int DEFAULT_CAPACITY
- See Also:
- Constant Field Values
-
-
Constructor Detail
-
MinMaxPriorityQueue
private MinMaxPriorityQueue(MinMaxPriorityQueue.Builder<? super E> builder, int queueSize)
-
-
Method Detail
-
create
public static <E extends java.lang.Comparable<E>> MinMaxPriorityQueue<E> create()
Creates a new min-max priority queue with default settings: natural order, no maximum size, no initial contents, and an initial expected size of 11.
-
create
public static <E extends java.lang.Comparable<E>> MinMaxPriorityQueue<E> create(java.lang.Iterable<? extends E> initialContents)
Creates a new min-max priority queue using natural order, no maximum size, and initially containing the given elements.
-
orderedBy
public static <B> MinMaxPriorityQueue.Builder<B> orderedBy(java.util.Comparator<B> comparator)
Creates and returns a new builder, configured to buildMinMaxPriorityQueue
instances that usecomparator
to determine the least and greatest elements.
-
expectedSize
public static MinMaxPriorityQueue.Builder<java.lang.Comparable> expectedSize(int expectedSize)
Creates and returns a new builder, configured to buildMinMaxPriorityQueue
instances sized appropriately to holdexpectedSize
elements.
-
maximumSize
public static MinMaxPriorityQueue.Builder<java.lang.Comparable> maximumSize(int maximumSize)
Creates and returns a new builder, configured to buildMinMaxPriorityQueue
instances that are limited tomaximumSize
elements. Each time a queue grows beyond this bound, it immediately removes its greatest element (according to its comparator), which might be the element that was just added.
-
size
public int size()
-
add
public boolean add(E element)
Adds the given element to this queue. If this queue has a maximum size, after addingelement
the queue will automatically evict its greatest element (according to its comparator), which may beelement
itself.
-
addAll
public boolean addAll(java.util.Collection<? extends E> newElements)
-
offer
public boolean offer(E element)
Adds the given element to this queue. If this queue has a maximum size, after addingelement
the queue will automatically evict its greatest element (according to its comparator), which may beelement
itself.
-
poll
public E poll()
-
elementData
E elementData(int index)
-
peek
public E peek()
-
getMaxElementIndex
private int getMaxElementIndex()
Returns the index of the max element.
-
pollFirst
public E pollFirst()
Removes and returns the least element of this queue, or returnsnull
if the queue is empty.
-
removeFirst
public E removeFirst()
Removes and returns the least element of this queue.- Throws:
java.util.NoSuchElementException
- if the queue is empty
-
peekFirst
public E peekFirst()
Retrieves, but does not remove, the least element of this queue, or returnsnull
if the queue is empty.
-
pollLast
public E pollLast()
Removes and returns the greatest element of this queue, or returnsnull
if the queue is empty.
-
removeLast
public E removeLast()
Removes and returns the greatest element of this queue.- Throws:
java.util.NoSuchElementException
- if the queue is empty
-
peekLast
public E peekLast()
Retrieves, but does not remove, the greatest element of this queue, or returnsnull
if the queue is empty.
-
removeAt
MinMaxPriorityQueue.MoveDesc<E> removeAt(int index)
Removes the element at positionindex
.Normally this method leaves the elements at up to
index - 1
, inclusive, untouched. Under these circumstances, it returnsnull
.Occasionally, in order to maintain the heap invariant, it must swap a later element of the list with one before
index
. Under these circumstances it returns a pair of elements as aMinMaxPriorityQueue.MoveDesc
. The first one is the element that was previously at the end of the heap and is now at some position beforeindex
. The second element is the one that was swapped down to replace the element atindex
. This fact is used by iterator.remove so as to visit elements during a traversal once and only once.
-
fillHole
private MinMaxPriorityQueue.MoveDesc<E> fillHole(int index, E toTrickle)
-
removeAndGet
private E removeAndGet(int index)
Removes and returns the value atindex
.
-
heapForIndex
private MinMaxPriorityQueue.Heap heapForIndex(int i)
-
isEvenLevel
static boolean isEvenLevel(int index)
-
isIntact
boolean isIntact()
Returnstrue
if the MinMax heap structure holds. This is only used in testing.TODO(kevinb): move to the test class?
-
iterator
public java.util.Iterator<E> iterator()
Returns an iterator over the elements contained in this collection, in no particular order.The iterator is fail-fast: If the MinMaxPriorityQueue is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will generally throw a
ConcurrentModificationException
. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw
ConcurrentModificationException
on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.
-
clear
public void clear()
-
toArray
public java.lang.Object[] toArray()
-
comparator
public java.util.Comparator<? super E> comparator()
Returns the comparator used to order the elements in this queue. Obeys the general contract ofPriorityQueue.comparator
, but returnsOrdering.natural()
instead ofnull
to indicate natural ordering.
-
capacity
int capacity()
-
initialQueueSize
static int initialQueueSize(int configuredExpectedSize, int maximumSize, java.lang.Iterable<?> initialContents)
-
growIfNeeded
private void growIfNeeded()
-
calculateNewCapacity
private int calculateNewCapacity()
Returns ~2x the old capacity if small; ~1.5x otherwise.
-
capAtMaximumSize
private static int capAtMaximumSize(int queueSize, int maximumSize)
There's no reason for the queueSize to ever be more than maxSize + 1
-
-