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