• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.collect;
18 
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21 import static com.google.common.base.Preconditions.checkPositionIndex;
22 import static com.google.common.base.Preconditions.checkState;
23 import static com.google.common.collect.CollectPreconditions.checkRemove;
24 
25 import com.google.common.annotations.Beta;
26 import com.google.common.annotations.VisibleForTesting;
27 import com.google.common.math.IntMath;
28 
29 import java.util.AbstractQueue;
30 import java.util.ArrayDeque;
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.Comparator;
35 import java.util.ConcurrentModificationException;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.NoSuchElementException;
39 import java.util.PriorityQueue;
40 import java.util.Queue;
41 
42 /**
43  * A double-ended priority queue, which provides constant-time access to both
44  * its least element and its greatest element, as determined by the queue's
45  * specified comparator. If no comparator is given at construction time, the
46  * natural order of elements is used.
47  *
48  * <p>As a {@link Queue} it functions exactly as a {@link PriorityQueue}: its
49  * head element -- the implicit target of the methods {@link #peek()}, {@link
50  * #poll()} and {@link #remove()} -- is defined as the <i>least</i> element in
51  * the queue according to the queue's comparator. But unlike a regular priority
52  * queue, the methods {@link #peekLast}, {@link #pollLast} and
53  * {@link #removeLast} are also provided, to act on the <i>greatest</i> element
54  * in the queue instead.
55  *
56  * <p>A min-max priority queue can be configured with a maximum size. If so,
57  * each time the size of the queue exceeds that value, the queue automatically
58  * removes its greatest element according to its comparator (which might be the
59  * element that was just added). This is different from conventional bounded
60  * queues, which either block or reject new elements when full.
61  *
62  * <p>This implementation is based on the
63  * <a href="http://portal.acm.org/citation.cfm?id=6621">min-max heap</a>
64  * developed by Atkinson, et al. Unlike many other double-ended priority queues,
65  * it stores elements in a single array, as compact as the traditional heap data
66  * structure used in {@link PriorityQueue}.
67  *
68  * <p>This class is not thread-safe, and does not accept null elements.
69  *
70  * <p><i>Performance notes:</i>
71  *
72  * <ul>
73  * <li>The retrieval operations {@link #peek}, {@link #peekFirst}, {@link
74  *     #peekLast}, {@link #element}, and {@link #size} are constant-time
75  * <li>The enqueing and dequeing operations ({@link #offer}, {@link #add}, and
76  *     all the forms of {@link #poll} and {@link #remove()}) run in {@code
77  *     O(log n) time}
78  * <li>The {@link #remove(Object)} and {@link #contains} operations require
79  *     linear ({@code O(n)}) time
80  * <li>If you only access one end of the queue, and don't use a maximum size,
81  *     this class is functionally equivalent to {@link PriorityQueue}, but
82  *     significantly slower.
83  * </ul>
84  *
85  * @author Sverre Sundsdal
86  * @author Torbjorn Gannholm
87  * @since 8.0
88  */
89 // TODO(kevinb): GWT compatibility
90 @Beta
91 public final class MinMaxPriorityQueue<E> extends AbstractQueue<E> {
92 
93   /**
94    * Creates a new min-max priority queue with default settings: natural order,
95    * no maximum size, no initial contents, and an initial expected size of 11.
96    */
create()97   public static <E extends Comparable<E>> MinMaxPriorityQueue<E> create() {
98     return new Builder<Comparable>(Ordering.natural()).create();
99   }
100 
101   /**
102    * Creates a new min-max priority queue using natural order, no maximum size,
103    * and initially containing the given elements.
104    */
create( Iterable<? extends E> initialContents)105   public static <E extends Comparable<E>> MinMaxPriorityQueue<E> create(
106       Iterable<? extends E> initialContents) {
107     return new Builder<E>(Ordering.<E>natural()).create(initialContents);
108   }
109 
110   /**
111    * Creates and returns a new builder, configured to build {@code
112    * MinMaxPriorityQueue} instances that use {@code comparator} to determine the
113    * least and greatest elements.
114    */
orderedBy(Comparator<B> comparator)115   public static <B> Builder<B> orderedBy(Comparator<B> comparator) {
116     return new Builder<B>(comparator);
117   }
118 
119   /**
120    * Creates and returns a new builder, configured to build {@code
121    * MinMaxPriorityQueue} instances sized appropriately to hold {@code
122    * expectedSize} elements.
123    */
expectedSize(int expectedSize)124   public static Builder<Comparable> expectedSize(int expectedSize) {
125     return new Builder<Comparable>(Ordering.natural())
126         .expectedSize(expectedSize);
127   }
128 
129   /**
130    * Creates and returns a new builder, configured to build {@code
131    * MinMaxPriorityQueue} instances that are limited to {@code maximumSize}
132    * elements. Each time a queue grows beyond this bound, it immediately
133    * removes its greatest element (according to its comparator), which might be
134    * the element that was just added.
135    */
maximumSize(int maximumSize)136   public static Builder<Comparable> maximumSize(int maximumSize) {
137     return new Builder<Comparable>(Ordering.natural())
138         .maximumSize(maximumSize);
139   }
140 
141   /**
142    * The builder class used in creation of min-max priority queues. Instead of
143    * constructing one directly, use {@link
144    * MinMaxPriorityQueue#orderedBy(Comparator)}, {@link
145    * MinMaxPriorityQueue#expectedSize(int)} or {@link
146    * MinMaxPriorityQueue#maximumSize(int)}.
147    *
148    * @param <B> the upper bound on the eventual type that can be produced by
149    *     this builder (for example, a {@code Builder<Number>} can produce a
150    *     {@code Queue<Number>} or {@code Queue<Integer>} but not a {@code
151    *     Queue<Object>}).
152    * @since 8.0
153    */
154   @Beta
155   public static final class Builder<B> {
156     /*
157      * TODO(kevinb): when the dust settles, see if we still need this or can
158      * just default to DEFAULT_CAPACITY.
159      */
160     private static final int UNSET_EXPECTED_SIZE = -1;
161 
162     private final Comparator<B> comparator;
163     private int expectedSize = UNSET_EXPECTED_SIZE;
164     private int maximumSize = Integer.MAX_VALUE;
165 
Builder(Comparator<B> comparator)166     private Builder(Comparator<B> comparator) {
167       this.comparator = checkNotNull(comparator);
168     }
169 
170     /**
171      * Configures this builder to build min-max priority queues with an initial
172      * expected size of {@code expectedSize}.
173      */
expectedSize(int expectedSize)174     public Builder<B> expectedSize(int expectedSize) {
175       checkArgument(expectedSize >= 0);
176       this.expectedSize = expectedSize;
177       return this;
178     }
179 
180     /**
181      * Configures this builder to build {@code MinMaxPriorityQueue} instances
182      * that are limited to {@code maximumSize} elements. Each time a queue grows
183      * beyond this bound, it immediately removes its greatest element (according
184      * to its comparator), which might be the element that was just added.
185      */
maximumSize(int maximumSize)186     public Builder<B> maximumSize(int maximumSize) {
187       checkArgument(maximumSize > 0);
188       this.maximumSize = maximumSize;
189       return this;
190     }
191 
192     /**
193      * Builds a new min-max priority queue using the previously specified
194      * options, and having no initial contents.
195      */
create()196     public <T extends B> MinMaxPriorityQueue<T> create() {
197       return create(Collections.<T>emptySet());
198     }
199 
200     /**
201      * Builds a new min-max priority queue using the previously specified
202      * options, and having the given initial elements.
203      */
create( Iterable<? extends T> initialContents)204     public <T extends B> MinMaxPriorityQueue<T> create(
205         Iterable<? extends T> initialContents) {
206       MinMaxPriorityQueue<T> queue = new MinMaxPriorityQueue<T>(
207           this, initialQueueSize(expectedSize, maximumSize, initialContents));
208       for (T element : initialContents) {
209         queue.offer(element);
210       }
211       return queue;
212     }
213 
214     @SuppressWarnings("unchecked") // safe "contravariant cast"
ordering()215     private <T extends B> Ordering<T> ordering() {
216       return Ordering.from((Comparator<T>) comparator);
217     }
218   }
219 
220   private final Heap minHeap;
221   private final Heap maxHeap;
222   @VisibleForTesting final int maximumSize;
223   private Object[] queue;
224   private int size;
225   private int modCount;
226 
MinMaxPriorityQueue(Builder<? super E> builder, int queueSize)227   private MinMaxPriorityQueue(Builder<? super E> builder, int queueSize) {
228     Ordering<E> ordering = builder.ordering();
229     this.minHeap = new Heap(ordering);
230     this.maxHeap = new Heap(ordering.reverse());
231     minHeap.otherHeap = maxHeap;
232     maxHeap.otherHeap = minHeap;
233 
234     this.maximumSize = builder.maximumSize;
235     // TODO(kevinb): pad?
236     this.queue = new Object[queueSize];
237   }
238 
size()239   @Override public int size() {
240     return size;
241   }
242 
243   /**
244    * Adds the given element to this queue. If this queue has a maximum size,
245    * after adding {@code element} the queue will automatically evict its
246    * greatest element (according to its comparator), which may be {@code
247    * element} itself.
248    *
249    * @return {@code true} always
250    */
add(E element)251   @Override public boolean add(E element) {
252     offer(element);
253     return true;
254   }
255 
addAll(Collection<? extends E> newElements)256   @Override public boolean addAll(Collection<? extends E> newElements) {
257     boolean modified = false;
258     for (E element : newElements) {
259       offer(element);
260       modified = true;
261     }
262     return modified;
263   }
264 
265   /**
266    * Adds the given element to this queue. If this queue has a maximum size,
267    * after adding {@code element} the queue will automatically evict its
268    * greatest element (according to its comparator), which may be {@code
269    * element} itself.
270    */
offer(E element)271   @Override public boolean offer(E element) {
272     checkNotNull(element);
273     modCount++;
274     int insertIndex = size++;
275 
276     growIfNeeded();
277 
278     // Adds the element to the end of the heap and bubbles it up to the correct
279     // position.
280     heapForIndex(insertIndex).bubbleUp(insertIndex, element);
281     return size <= maximumSize || pollLast() != element;
282   }
283 
poll()284   @Override public E poll() {
285     return isEmpty() ? null : removeAndGet(0);
286   }
287 
288   @SuppressWarnings("unchecked") // we must carefully only allow Es to get in
elementData(int index)289   E elementData(int index) {
290     return (E) queue[index];
291   }
292 
peek()293   @Override public E peek() {
294     return isEmpty() ? null : elementData(0);
295   }
296 
297   /**
298    * Returns the index of the max element.
299    */
getMaxElementIndex()300   private int getMaxElementIndex() {
301     switch (size) {
302       case 1:
303         return 0; // The lone element in the queue is the maximum.
304       case 2:
305         return 1; // The lone element in the maxHeap is the maximum.
306       default:
307         // The max element must sit on the first level of the maxHeap. It is
308         // actually the *lesser* of the two from the maxHeap's perspective.
309         return (maxHeap.compareElements(1, 2) <= 0) ? 1 : 2;
310     }
311   }
312 
313   /**
314    * Removes and returns the least element of this queue, or returns {@code
315    * null} if the queue is empty.
316    */
pollFirst()317   public E pollFirst() {
318     return poll();
319   }
320 
321   /**
322    * Removes and returns the least element of this queue.
323    *
324    * @throws NoSuchElementException if the queue is empty
325    */
removeFirst()326   public E removeFirst() {
327     return remove();
328   }
329 
330   /**
331    * Retrieves, but does not remove, the least element of this queue, or returns
332    * {@code null} if the queue is empty.
333    */
peekFirst()334   public E peekFirst() {
335     return peek();
336   }
337 
338   /**
339    * Removes and returns the greatest element of this queue, or returns {@code
340    * null} if the queue is empty.
341    */
pollLast()342   public E pollLast() {
343     return isEmpty() ? null : removeAndGet(getMaxElementIndex());
344   }
345 
346   /**
347    * Removes and returns the greatest element of this queue.
348    *
349    * @throws NoSuchElementException if the queue is empty
350    */
removeLast()351   public E removeLast() {
352     if (isEmpty()) {
353       throw new NoSuchElementException();
354     }
355     return removeAndGet(getMaxElementIndex());
356   }
357 
358   /**
359    * Retrieves, but does not remove, the greatest element of this queue, or
360    * returns {@code null} if the queue is empty.
361    */
peekLast()362   public E peekLast() {
363     return isEmpty() ? null : elementData(getMaxElementIndex());
364   }
365 
366   /**
367    * Removes the element at position {@code index}.
368    *
369    * <p>Normally this method leaves the elements at up to {@code index - 1},
370    * inclusive, untouched.  Under these circumstances, it returns {@code null}.
371    *
372    * <p>Occasionally, in order to maintain the heap invariant, it must swap a
373    * later element of the list with one before {@code index}. Under these
374    * circumstances it returns a pair of elements as a {@link MoveDesc}. The
375    * first one is the element that was previously at the end of the heap and is
376    * now at some position before {@code index}. The second element is the one
377    * that was swapped down to replace the element at {@code index}. This fact is
378    * used by iterator.remove so as to visit elements during a traversal once and
379    * only once.
380    */
removeAt(int index)381   @VisibleForTesting MoveDesc<E> removeAt(int index) {
382     checkPositionIndex(index, size);
383     modCount++;
384     size--;
385     if (size == index) {
386       queue[size] = null;
387       return null;
388     }
389     E actualLastElement = elementData(size);
390     int lastElementAt = heapForIndex(size)
391         .getCorrectLastElement(actualLastElement);
392     E toTrickle = elementData(size);
393     queue[size] = null;
394     MoveDesc<E> changes = fillHole(index, toTrickle);
395     if (lastElementAt < index) {
396       // Last element is moved to before index, swapped with trickled element.
397       if (changes == null) {
398         // The trickled element is still after index.
399         return new MoveDesc<E>(actualLastElement, toTrickle);
400       } else {
401         // The trickled element is back before index, but the replaced element
402         // has now been moved after index.
403         return new MoveDesc<E>(actualLastElement, changes.replaced);
404       }
405     }
406     // Trickled element was after index to begin with, no adjustment needed.
407     return changes;
408   }
409 
fillHole(int index, E toTrickle)410   private MoveDesc<E> fillHole(int index, E toTrickle) {
411     Heap heap = heapForIndex(index);
412     // We consider elementData(index) a "hole", and we want to fill it
413     // with the last element of the heap, toTrickle.
414     // Since the last element of the heap is from the bottom level, we
415     // optimistically fill index position with elements from lower levels,
416     // moving the hole down. In most cases this reduces the number of
417     // comparisons with toTrickle, but in some cases we will need to bubble it
418     // all the way up again.
419     int vacated = heap.fillHoleAt(index);
420     // Try to see if toTrickle can be bubbled up min levels.
421     int bubbledTo = heap.bubbleUpAlternatingLevels(vacated, toTrickle);
422     if (bubbledTo == vacated) {
423       // Could not bubble toTrickle up min levels, try moving
424       // it from min level to max level (or max to min level) and bubble up
425       // there.
426       return heap.tryCrossOverAndBubbleUp(index, vacated, toTrickle);
427     } else {
428       return (bubbledTo < index)
429           ? new MoveDesc<E>(toTrickle, elementData(index))
430           : null;
431     }
432   }
433 
434   // Returned from removeAt() to iterator.remove()
435   static class MoveDesc<E> {
436     final E toTrickle;
437     final E replaced;
438 
MoveDesc(E toTrickle, E replaced)439     MoveDesc(E toTrickle, E replaced) {
440       this.toTrickle = toTrickle;
441       this.replaced = replaced;
442     }
443   }
444 
445   /**
446    * Removes and returns the value at {@code index}.
447    */
removeAndGet(int index)448   private E removeAndGet(int index) {
449     E value = elementData(index);
450     removeAt(index);
451     return value;
452   }
453 
heapForIndex(int i)454   private Heap heapForIndex(int i) {
455     return isEvenLevel(i) ? minHeap : maxHeap;
456   }
457 
458   private static final int EVEN_POWERS_OF_TWO = 0x55555555;
459   private static final int ODD_POWERS_OF_TWO = 0xaaaaaaaa;
460 
isEvenLevel(int index)461   @VisibleForTesting static boolean isEvenLevel(int index) {
462     int oneBased = index + 1;
463     checkState(oneBased > 0, "negative index");
464     return (oneBased & EVEN_POWERS_OF_TWO) > (oneBased & ODD_POWERS_OF_TWO);
465   }
466 
467   /**
468    * Returns {@code true} if the MinMax heap structure holds. This is only used
469    * in testing.
470    *
471    * TODO(kevinb): move to the test class?
472    */
isIntact()473   @VisibleForTesting boolean isIntact() {
474     for (int i = 1; i < size; i++) {
475       if (!heapForIndex(i).verifyIndex(i)) {
476         return false;
477       }
478     }
479     return true;
480   }
481 
482   /**
483    * Each instance of MinMaxPriortyQueue encapsulates two instances of Heap:
484    * a min-heap and a max-heap. Conceptually, these might each have their own
485    * array for storage, but for efficiency's sake they are stored interleaved on
486    * alternate heap levels in the same array (MMPQ.queue).
487    */
488   private class Heap {
489     final Ordering<E> ordering;
490     Heap otherHeap;
491 
Heap(Ordering<E> ordering)492     Heap(Ordering<E> ordering) {
493       this.ordering = ordering;
494     }
495 
compareElements(int a, int b)496     int compareElements(int a, int b) {
497       return ordering.compare(elementData(a), elementData(b));
498     }
499 
500     /**
501      * Tries to move {@code toTrickle} from a min to a max level and
502      * bubble up there. If it moved before {@code removeIndex} this method
503      * returns a pair as described in {@link #removeAt}.
504      */
tryCrossOverAndBubbleUp( int removeIndex, int vacated, E toTrickle)505     MoveDesc<E> tryCrossOverAndBubbleUp(
506         int removeIndex, int vacated, E toTrickle) {
507       int crossOver = crossOver(vacated, toTrickle);
508       if (crossOver == vacated) {
509         return null;
510       }
511       // Successfully crossed over from min to max.
512       // Bubble up max levels.
513       E parent;
514       // If toTrickle is moved up to a parent of removeIndex, the parent is
515       // placed in removeIndex position. We must return that to the iterator so
516       // that it knows to skip it.
517       if (crossOver < removeIndex) {
518         // We crossed over to the parent level in crossOver, so the parent
519         // has already been moved.
520         parent = elementData(removeIndex);
521       } else {
522         parent = elementData(getParentIndex(removeIndex));
523       }
524       // bubble it up the opposite heap
525       if (otherHeap.bubbleUpAlternatingLevels(crossOver, toTrickle)
526           < removeIndex) {
527         return new MoveDesc<E>(toTrickle, parent);
528       } else {
529         return null;
530       }
531     }
532 
533     /**
534      * Bubbles a value from {@code index} up the appropriate heap if required.
535      */
bubbleUp(int index, E x)536     void bubbleUp(int index, E x) {
537       int crossOver = crossOverUp(index, x);
538 
539       Heap heap;
540       if (crossOver == index) {
541         heap = this;
542       } else {
543         index = crossOver;
544         heap = otherHeap;
545       }
546       heap.bubbleUpAlternatingLevels(index, x);
547     }
548 
549     /**
550      * Bubbles a value from {@code index} up the levels of this heap, and
551      * returns the index the element ended up at.
552      */
bubbleUpAlternatingLevels(int index, E x)553     int bubbleUpAlternatingLevels(int index, E x) {
554       while (index > 2) {
555         int grandParentIndex = getGrandparentIndex(index);
556         E e = elementData(grandParentIndex);
557         if (ordering.compare(e, x) <= 0) {
558           break;
559         }
560         queue[index] = e;
561         index = grandParentIndex;
562       }
563       queue[index] = x;
564       return index;
565     }
566 
567     /**
568      * Returns the index of minimum value between {@code index} and
569      * {@code index + len}, or {@code -1} if {@code index} is greater than
570      * {@code size}.
571      */
findMin(int index, int len)572     int findMin(int index, int len) {
573       if (index >= size) {
574         return -1;
575       }
576       checkState(index > 0);
577       int limit = Math.min(index, size - len) + len;
578       int minIndex = index;
579       for (int i = index + 1; i < limit; i++) {
580         if (compareElements(i, minIndex) < 0) {
581           minIndex = i;
582         }
583       }
584       return minIndex;
585     }
586 
587     /**
588      * Returns the minimum child or {@code -1} if no child exists.
589      */
findMinChild(int index)590     int findMinChild(int index) {
591       return findMin(getLeftChildIndex(index), 2);
592     }
593 
594     /**
595      * Returns the minimum grand child or -1 if no grand child exists.
596      */
findMinGrandChild(int index)597     int findMinGrandChild(int index) {
598       int leftChildIndex = getLeftChildIndex(index);
599       if (leftChildIndex < 0) {
600         return -1;
601       }
602       return findMin(getLeftChildIndex(leftChildIndex), 4);
603     }
604 
605     /**
606      * Moves an element one level up from a min level to a max level
607      * (or vice versa).
608      * Returns the new position of the element.
609      */
crossOverUp(int index, E x)610     int crossOverUp(int index, E x) {
611       if (index == 0) {
612         queue[0] = x;
613         return 0;
614       }
615       int parentIndex = getParentIndex(index);
616       E parentElement = elementData(parentIndex);
617       if (parentIndex != 0) {
618         // This is a guard for the case of the childless uncle.
619         // Since the end of the array is actually the middle of the heap,
620         // a smaller childless uncle can become a child of x when we
621         // bubble up alternate levels, violating the invariant.
622         int grandparentIndex = getParentIndex(parentIndex);
623         int uncleIndex = getRightChildIndex(grandparentIndex);
624         if (uncleIndex != parentIndex
625             && getLeftChildIndex(uncleIndex) >= size) {
626           E uncleElement = elementData(uncleIndex);
627           if (ordering.compare(uncleElement, parentElement) < 0) {
628             parentIndex = uncleIndex;
629             parentElement = uncleElement;
630           }
631         }
632       }
633       if (ordering.compare(parentElement, x) < 0) {
634         queue[index] = parentElement;
635         queue[parentIndex] = x;
636         return parentIndex;
637       }
638       queue[index] = x;
639       return index;
640     }
641 
642     /**
643      * Returns the conceptually correct last element of the heap.
644      *
645      * <p>Since the last element of the array is actually in the
646      * middle of the sorted structure, a childless uncle node could be
647      * smaller, which would corrupt the invariant if this element
648      * becomes the new parent of the uncle. In that case, we first
649      * switch the last element with its uncle, before returning.
650      */
getCorrectLastElement(E actualLastElement)651     int getCorrectLastElement(E actualLastElement) {
652       int parentIndex = getParentIndex(size);
653       if (parentIndex != 0) {
654         int grandparentIndex = getParentIndex(parentIndex);
655         int uncleIndex = getRightChildIndex(grandparentIndex);
656         if (uncleIndex != parentIndex
657             && getLeftChildIndex(uncleIndex) >= size) {
658           E uncleElement = elementData(uncleIndex);
659           if (ordering.compare(uncleElement, actualLastElement) < 0) {
660             queue[uncleIndex] = actualLastElement;
661             queue[size] = uncleElement;
662             return uncleIndex;
663           }
664         }
665       }
666       return size;
667     }
668 
669     /**
670      * Crosses an element over to the opposite heap by moving it one level down
671      * (or up if there are no elements below it).
672      *
673      * Returns the new position of the element.
674      */
crossOver(int index, E x)675     int crossOver(int index, E x) {
676       int minChildIndex = findMinChild(index);
677       // TODO(kevinb): split the && into two if's and move crossOverUp so it's
678       // only called when there's no child.
679       if ((minChildIndex > 0)
680           && (ordering.compare(elementData(minChildIndex), x) < 0)) {
681         queue[index] = elementData(minChildIndex);
682         queue[minChildIndex] = x;
683         return minChildIndex;
684       }
685       return crossOverUp(index, x);
686     }
687 
688     /**
689      * Fills the hole at {@code index} by moving in the least of its
690      * grandchildren to this position, then recursively filling the new hole
691      * created.
692      *
693      * @return the position of the new hole (where the lowest grandchild moved
694      *     from, that had no grandchild to replace it)
695      */
fillHoleAt(int index)696     int fillHoleAt(int index) {
697       int minGrandchildIndex;
698       while ((minGrandchildIndex = findMinGrandChild(index)) > 0) {
699         queue[index] = elementData(minGrandchildIndex);
700         index = minGrandchildIndex;
701       }
702       return index;
703     }
704 
verifyIndex(int i)705     private boolean verifyIndex(int i) {
706       if ((getLeftChildIndex(i) < size)
707           && (compareElements(i, getLeftChildIndex(i)) > 0)) {
708         return false;
709       }
710       if ((getRightChildIndex(i) < size)
711           && (compareElements(i, getRightChildIndex(i)) > 0)) {
712         return false;
713       }
714       if ((i > 0) && (compareElements(i, getParentIndex(i)) > 0)) {
715         return false;
716       }
717       if ((i > 2) && (compareElements(getGrandparentIndex(i), i) > 0)) {
718         return false;
719       }
720       return true;
721     }
722 
723     // These would be static if inner classes could have static members.
724 
getLeftChildIndex(int i)725     private int getLeftChildIndex(int i) {
726       return i * 2 + 1;
727     }
728 
getRightChildIndex(int i)729     private int getRightChildIndex(int i) {
730       return i * 2 + 2;
731     }
732 
getParentIndex(int i)733     private int getParentIndex(int i) {
734       return (i - 1) / 2;
735     }
736 
getGrandparentIndex(int i)737     private int getGrandparentIndex(int i) {
738       return getParentIndex(getParentIndex(i)); // (i - 3) / 4
739     }
740   }
741 
742   /**
743    * Iterates the elements of the queue in no particular order.
744    *
745    * If the underlying queue is modified during iteration an exception will be
746    * thrown.
747    */
748   private class QueueIterator implements Iterator<E> {
749     private int cursor = -1;
750     private int expectedModCount = modCount;
751     private Queue<E> forgetMeNot;
752     private List<E> skipMe;
753     private E lastFromForgetMeNot;
754     private boolean canRemove;
755 
hasNext()756     @Override public boolean hasNext() {
757       checkModCount();
758       return (nextNotInSkipMe(cursor + 1) < size())
759           || ((forgetMeNot != null) && !forgetMeNot.isEmpty());
760     }
761 
next()762     @Override public E next() {
763       checkModCount();
764       int tempCursor = nextNotInSkipMe(cursor + 1);
765       if (tempCursor < size()) {
766         cursor = tempCursor;
767         canRemove = true;
768         return elementData(cursor);
769       } else if (forgetMeNot != null) {
770         cursor = size();
771         lastFromForgetMeNot = forgetMeNot.poll();
772         if (lastFromForgetMeNot != null) {
773           canRemove = true;
774           return lastFromForgetMeNot;
775         }
776       }
777       throw new NoSuchElementException(
778           "iterator moved past last element in queue.");
779     }
780 
remove()781     @Override public void remove() {
782       checkRemove(canRemove);
783       checkModCount();
784       canRemove = false;
785       expectedModCount++;
786       if (cursor < size()) {
787         MoveDesc<E> moved = removeAt(cursor);
788         if (moved != null) {
789           if (forgetMeNot == null) {
790             forgetMeNot = new ArrayDeque<E>();
791             skipMe = new ArrayList<E>(3);
792           }
793           forgetMeNot.add(moved.toTrickle);
794           skipMe.add(moved.replaced);
795         }
796         cursor--;
797       } else { // we must have set lastFromForgetMeNot in next()
798         checkState(removeExact(lastFromForgetMeNot));
799         lastFromForgetMeNot = null;
800       }
801     }
802 
803     // Finds only this exact instance, not others that are equals()
containsExact(Iterable<E> elements, E target)804     private boolean containsExact(Iterable<E> elements, E target) {
805       for (E element : elements) {
806         if (element == target) {
807           return true;
808         }
809       }
810       return false;
811     }
812 
813     // Removes only this exact instance, not others that are equals()
removeExact(Object target)814     boolean removeExact(Object target) {
815       for (int i = 0; i < size; i++) {
816         if (queue[i] == target) {
817           removeAt(i);
818           return true;
819         }
820       }
821       return false;
822     }
823 
checkModCount()824     void checkModCount() {
825       if (modCount != expectedModCount) {
826         throw new ConcurrentModificationException();
827       }
828     }
829 
830     /**
831      * Returns the index of the first element after {@code c} that is not in
832      * {@code skipMe} and returns {@code size()} if there is no such element.
833      */
nextNotInSkipMe(int c)834     private int nextNotInSkipMe(int c) {
835       if (skipMe != null) {
836         while (c < size() && containsExact(skipMe, elementData(c))) {
837           c++;
838         }
839       }
840       return c;
841     }
842   }
843 
844   /**
845    * Returns an iterator over the elements contained in this collection,
846    * <i>in no particular order</i>.
847    *
848    * <p>The iterator is <i>fail-fast</i>: If the MinMaxPriorityQueue is modified
849    * at any time after the iterator is created, in any way except through the
850    * iterator's own remove method, the iterator will generally throw a
851    * {@link ConcurrentModificationException}. Thus, in the face of concurrent
852    * modification, the iterator fails quickly and cleanly, rather than risking
853    * arbitrary, non-deterministic behavior at an undetermined time in the
854    * future.
855    *
856    * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
857    * as it is, generally speaking, impossible to make any hard guarantees in the
858    * presence of unsynchronized concurrent modification.  Fail-fast iterators
859    * throw {@code ConcurrentModificationException} on a best-effort basis.
860    * Therefore, it would be wrong to write a program that depended on this
861    * exception for its correctness: <i>the fail-fast behavior of iterators
862    * should be used only to detect bugs.</i>
863    *
864    * @return an iterator over the elements contained in this collection
865    */
iterator()866   @Override public Iterator<E> iterator() {
867     return new QueueIterator();
868   }
869 
clear()870   @Override public void clear() {
871     for (int i = 0; i < size; i++) {
872       queue[i] = null;
873     }
874     size = 0;
875   }
876 
toArray()877   @Override public Object[] toArray() {
878     Object[] copyTo = new Object[size];
879     System.arraycopy(queue, 0, copyTo, 0, size);
880     return copyTo;
881   }
882 
883   /**
884    * Returns the comparator used to order the elements in this queue. Obeys the
885    * general contract of {@link PriorityQueue#comparator}, but returns {@link
886    * Ordering#natural} instead of {@code null} to indicate natural ordering.
887    */
comparator()888   public Comparator<? super E> comparator() {
889     return minHeap.ordering;
890   }
891 
capacity()892   @VisibleForTesting int capacity() {
893     return queue.length;
894   }
895 
896   // Size/capacity-related methods
897 
898   private static final int DEFAULT_CAPACITY = 11;
899 
initialQueueSize(int configuredExpectedSize, int maximumSize, Iterable<?> initialContents)900   @VisibleForTesting static int initialQueueSize(int configuredExpectedSize,
901       int maximumSize, Iterable<?> initialContents) {
902     // Start with what they said, if they said it, otherwise DEFAULT_CAPACITY
903     int result = (configuredExpectedSize == Builder.UNSET_EXPECTED_SIZE)
904         ? DEFAULT_CAPACITY
905         : configuredExpectedSize;
906 
907     // Enlarge to contain initial contents
908     if (initialContents instanceof Collection) {
909       int initialSize = ((Collection<?>) initialContents).size();
910       result = Math.max(result, initialSize);
911     }
912 
913     // Now cap it at maxSize + 1
914     return capAtMaximumSize(result, maximumSize);
915   }
916 
growIfNeeded()917   private void growIfNeeded() {
918     if (size > queue.length) {
919       int newCapacity = calculateNewCapacity();
920       Object[] newQueue = new Object[newCapacity];
921       System.arraycopy(queue, 0, newQueue, 0, queue.length);
922       queue = newQueue;
923     }
924   }
925 
926   /** Returns ~2x the old capacity if small; ~1.5x otherwise. */
calculateNewCapacity()927   private int calculateNewCapacity() {
928     int oldCapacity = queue.length;
929     int newCapacity = (oldCapacity < 64)
930         ? (oldCapacity + 1) * 2
931         : IntMath.checkedMultiply(oldCapacity / 2, 3);
932     return capAtMaximumSize(newCapacity, maximumSize);
933   }
934 
935   /** There's no reason for the queueSize to ever be more than maxSize + 1 */
capAtMaximumSize(int queueSize, int maximumSize)936   private static int capAtMaximumSize(int queueSize, int maximumSize) {
937     return Math.min(queueSize - 1, maximumSize) + 1; // don't overflow
938   }
939 }
940