rt/emul/compact/src/main/java/java/util/PriorityQueue.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 17 Jan 2017 07:04:06 +0100
changeset 1985 cd1cc103a03c
parent 636 8d0be6a9a809
permissions -rw-r--r--
Implementation of ClassValue for bck2brwsr
     1 /*
     2  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.util;
    27 
    28 
    29 /**
    30  * An unbounded priority {@linkplain Queue queue} based on a priority heap.
    31  * The elements of the priority queue are ordered according to their
    32  * {@linkplain Comparable natural ordering}, or by a {@link Comparator}
    33  * provided at queue construction time, depending on which constructor is
    34  * used.  A priority queue does not permit {@code null} elements.
    35  * A priority queue relying on natural ordering also does not permit
    36  * insertion of non-comparable objects (doing so may result in
    37  * {@code ClassCastException}).
    38  *
    39  * <p>The <em>head</em> of this queue is the <em>least</em> element
    40  * with respect to the specified ordering.  If multiple elements are
    41  * tied for least value, the head is one of those elements -- ties are
    42  * broken arbitrarily.  The queue retrieval operations {@code poll},
    43  * {@code remove}, {@code peek}, and {@code element} access the
    44  * element at the head of the queue.
    45  *
    46  * <p>A priority queue is unbounded, but has an internal
    47  * <i>capacity</i> governing the size of an array used to store the
    48  * elements on the queue.  It is always at least as large as the queue
    49  * size.  As elements are added to a priority queue, its capacity
    50  * grows automatically.  The details of the growth policy are not
    51  * specified.
    52  *
    53  * <p>This class and its iterator implement all of the
    54  * <em>optional</em> methods of the {@link Collection} and {@link
    55  * Iterator} interfaces.  The Iterator provided in method {@link
    56  * #iterator()} is <em>not</em> guaranteed to traverse the elements of
    57  * the priority queue in any particular order. If you need ordered
    58  * traversal, consider using {@code Arrays.sort(pq.toArray())}.
    59  *
    60  * <p> <strong>Note that this implementation is not synchronized.</strong>
    61  * Multiple threads should not access a {@code PriorityQueue}
    62  * instance concurrently if any of the threads modifies the queue.
    63  * Instead, use the thread-safe {@link
    64  * java.util.concurrent.PriorityBlockingQueue} class.
    65  *
    66  * <p>Implementation note: this implementation provides
    67  * O(log(n)) time for the enqueing and dequeing methods
    68  * ({@code offer}, {@code poll}, {@code remove()} and {@code add});
    69  * linear time for the {@code remove(Object)} and {@code contains(Object)}
    70  * methods; and constant time for the retrieval methods
    71  * ({@code peek}, {@code element}, and {@code size}).
    72  *
    73  * <p>This class is a member of the
    74  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
    75  * Java Collections Framework</a>.
    76  *
    77  * @since 1.5
    78  * @author Josh Bloch, Doug Lea
    79  * @param <E> the type of elements held in this collection
    80  */
    81 public class PriorityQueue<E> extends AbstractQueue<E>
    82     implements java.io.Serializable {
    83 
    84     private static final long serialVersionUID = -7720805057305804111L;
    85 
    86     private static final int DEFAULT_INITIAL_CAPACITY = 11;
    87 
    88     /**
    89      * Priority queue represented as a balanced binary heap: the two
    90      * children of queue[n] are queue[2*n+1] and queue[2*(n+1)].  The
    91      * priority queue is ordered by comparator, or by the elements'
    92      * natural ordering, if comparator is null: For each node n in the
    93      * heap and each descendant d of n, n <= d.  The element with the
    94      * lowest value is in queue[0], assuming the queue is nonempty.
    95      */
    96     private transient Object[] queue;
    97 
    98     /**
    99      * The number of elements in the priority queue.
   100      */
   101     private int size = 0;
   102 
   103     /**
   104      * The comparator, or null if priority queue uses elements'
   105      * natural ordering.
   106      */
   107     private final Comparator<? super E> comparator;
   108 
   109     /**
   110      * The number of times this priority queue has been
   111      * <i>structurally modified</i>.  See AbstractList for gory details.
   112      */
   113     private transient int modCount = 0;
   114 
   115     /**
   116      * Creates a {@code PriorityQueue} with the default initial
   117      * capacity (11) that orders its elements according to their
   118      * {@linkplain Comparable natural ordering}.
   119      */
   120     public PriorityQueue() {
   121         this(DEFAULT_INITIAL_CAPACITY, null);
   122     }
   123 
   124     /**
   125      * Creates a {@code PriorityQueue} with the specified initial
   126      * capacity that orders its elements according to their
   127      * {@linkplain Comparable natural ordering}.
   128      *
   129      * @param initialCapacity the initial capacity for this priority queue
   130      * @throws IllegalArgumentException if {@code initialCapacity} is less
   131      *         than 1
   132      */
   133     public PriorityQueue(int initialCapacity) {
   134         this(initialCapacity, null);
   135     }
   136 
   137     /**
   138      * Creates a {@code PriorityQueue} with the specified initial capacity
   139      * that orders its elements according to the specified comparator.
   140      *
   141      * @param  initialCapacity the initial capacity for this priority queue
   142      * @param  comparator the comparator that will be used to order this
   143      *         priority queue.  If {@code null}, the {@linkplain Comparable
   144      *         natural ordering} of the elements will be used.
   145      * @throws IllegalArgumentException if {@code initialCapacity} is
   146      *         less than 1
   147      */
   148     public PriorityQueue(int initialCapacity,
   149                          Comparator<? super E> comparator) {
   150         // Note: This restriction of at least one is not actually needed,
   151         // but continues for 1.5 compatibility
   152         if (initialCapacity < 1)
   153             throw new IllegalArgumentException();
   154         this.queue = new Object[initialCapacity];
   155         this.comparator = comparator;
   156     }
   157 
   158     /**
   159      * Creates a {@code PriorityQueue} containing the elements in the
   160      * specified collection.  If the specified collection is an instance of
   161      * a {@link SortedSet} or is another {@code PriorityQueue}, this
   162      * priority queue will be ordered according to the same ordering.
   163      * Otherwise, this priority queue will be ordered according to the
   164      * {@linkplain Comparable natural ordering} of its elements.
   165      *
   166      * @param  c the collection whose elements are to be placed
   167      *         into this priority queue
   168      * @throws ClassCastException if elements of the specified collection
   169      *         cannot be compared to one another according to the priority
   170      *         queue's ordering
   171      * @throws NullPointerException if the specified collection or any
   172      *         of its elements are null
   173      */
   174     @SuppressWarnings("unchecked")
   175     public PriorityQueue(Collection<? extends E> c) {
   176         if (c instanceof SortedSet<?>) {
   177             SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
   178             this.comparator = (Comparator<? super E>) ss.comparator();
   179             initElementsFromCollection(ss);
   180         }
   181         else if (c instanceof PriorityQueue<?>) {
   182             PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c;
   183             this.comparator = (Comparator<? super E>) pq.comparator();
   184             initFromPriorityQueue(pq);
   185         }
   186         else {
   187             this.comparator = null;
   188             initFromCollection(c);
   189         }
   190     }
   191 
   192     /**
   193      * Creates a {@code PriorityQueue} containing the elements in the
   194      * specified priority queue.  This priority queue will be
   195      * ordered according to the same ordering as the given priority
   196      * queue.
   197      *
   198      * @param  c the priority queue whose elements are to be placed
   199      *         into this priority queue
   200      * @throws ClassCastException if elements of {@code c} cannot be
   201      *         compared to one another according to {@code c}'s
   202      *         ordering
   203      * @throws NullPointerException if the specified priority queue or any
   204      *         of its elements are null
   205      */
   206     @SuppressWarnings("unchecked")
   207     public PriorityQueue(PriorityQueue<? extends E> c) {
   208         this.comparator = (Comparator<? super E>) c.comparator();
   209         initFromPriorityQueue(c);
   210     }
   211 
   212     /**
   213      * Creates a {@code PriorityQueue} containing the elements in the
   214      * specified sorted set.   This priority queue will be ordered
   215      * according to the same ordering as the given sorted set.
   216      *
   217      * @param  c the sorted set whose elements are to be placed
   218      *         into this priority queue
   219      * @throws ClassCastException if elements of the specified sorted
   220      *         set cannot be compared to one another according to the
   221      *         sorted set's ordering
   222      * @throws NullPointerException if the specified sorted set or any
   223      *         of its elements are null
   224      */
   225     @SuppressWarnings("unchecked")
   226     public PriorityQueue(SortedSet<? extends E> c) {
   227         this.comparator = (Comparator<? super E>) c.comparator();
   228         initElementsFromCollection(c);
   229     }
   230 
   231     private void initFromPriorityQueue(PriorityQueue<? extends E> c) {
   232         if (c.getClass() == PriorityQueue.class) {
   233             this.queue = c.toArray();
   234             this.size = c.size();
   235         } else {
   236             initFromCollection(c);
   237         }
   238     }
   239 
   240     private void initElementsFromCollection(Collection<? extends E> c) {
   241         Object[] a = c.toArray();
   242         // If c.toArray incorrectly doesn't return Object[], copy it.
   243         if (a.getClass() != Object[].class)
   244             a = Arrays.copyOf(a, a.length, Object[].class);
   245         int len = a.length;
   246         if (len == 1 || this.comparator != null)
   247             for (int i = 0; i < len; i++)
   248                 if (a[i] == null)
   249                     throw new NullPointerException();
   250         this.queue = a;
   251         this.size = a.length;
   252     }
   253 
   254     /**
   255      * Initializes queue array with elements from the given Collection.
   256      *
   257      * @param c the collection
   258      */
   259     private void initFromCollection(Collection<? extends E> c) {
   260         initElementsFromCollection(c);
   261         heapify();
   262     }
   263 
   264     /**
   265      * The maximum size of array to allocate.
   266      * Some VMs reserve some header words in an array.
   267      * Attempts to allocate larger arrays may result in
   268      * OutOfMemoryError: Requested array size exceeds VM limit
   269      */
   270     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
   271 
   272     /**
   273      * Increases the capacity of the array.
   274      *
   275      * @param minCapacity the desired minimum capacity
   276      */
   277     private void grow(int minCapacity) {
   278         int oldCapacity = queue.length;
   279         // Double size if small; else grow by 50%
   280         int newCapacity = oldCapacity + ((oldCapacity < 64) ?
   281                                          (oldCapacity + 2) :
   282                                          (oldCapacity >> 1));
   283         // overflow-conscious code
   284         if (newCapacity - MAX_ARRAY_SIZE > 0)
   285             newCapacity = hugeCapacity(minCapacity);
   286         queue = Arrays.copyOf(queue, newCapacity);
   287     }
   288 
   289     private static int hugeCapacity(int minCapacity) {
   290         if (minCapacity < 0) // overflow
   291             throw new OutOfMemoryError();
   292         return (minCapacity > MAX_ARRAY_SIZE) ?
   293             Integer.MAX_VALUE :
   294             MAX_ARRAY_SIZE;
   295     }
   296 
   297     /**
   298      * Inserts the specified element into this priority queue.
   299      *
   300      * @return {@code true} (as specified by {@link Collection#add})
   301      * @throws ClassCastException if the specified element cannot be
   302      *         compared with elements currently in this priority queue
   303      *         according to the priority queue's ordering
   304      * @throws NullPointerException if the specified element is null
   305      */
   306     public boolean add(E e) {
   307         return offer(e);
   308     }
   309 
   310     /**
   311      * Inserts the specified element into this priority queue.
   312      *
   313      * @return {@code true} (as specified by {@link Queue#offer})
   314      * @throws ClassCastException if the specified element cannot be
   315      *         compared with elements currently in this priority queue
   316      *         according to the priority queue's ordering
   317      * @throws NullPointerException if the specified element is null
   318      */
   319     public boolean offer(E e) {
   320         if (e == null)
   321             throw new NullPointerException();
   322         modCount++;
   323         int i = size;
   324         if (i >= queue.length)
   325             grow(i + 1);
   326         size = i + 1;
   327         if (i == 0)
   328             queue[0] = e;
   329         else
   330             siftUp(i, e);
   331         return true;
   332     }
   333 
   334     public E peek() {
   335         if (size == 0)
   336             return null;
   337         return (E) queue[0];
   338     }
   339 
   340     private int indexOf(Object o) {
   341         if (o != null) {
   342             for (int i = 0; i < size; i++)
   343                 if (o.equals(queue[i]))
   344                     return i;
   345         }
   346         return -1;
   347     }
   348 
   349     /**
   350      * Removes a single instance of the specified element from this queue,
   351      * if it is present.  More formally, removes an element {@code e} such
   352      * that {@code o.equals(e)}, if this queue contains one or more such
   353      * elements.  Returns {@code true} if and only if this queue contained
   354      * the specified element (or equivalently, if this queue changed as a
   355      * result of the call).
   356      *
   357      * @param o element to be removed from this queue, if present
   358      * @return {@code true} if this queue changed as a result of the call
   359      */
   360     public boolean remove(Object o) {
   361         int i = indexOf(o);
   362         if (i == -1)
   363             return false;
   364         else {
   365             removeAt(i);
   366             return true;
   367         }
   368     }
   369 
   370     /**
   371      * Version of remove using reference equality, not equals.
   372      * Needed by iterator.remove.
   373      *
   374      * @param o element to be removed from this queue, if present
   375      * @return {@code true} if removed
   376      */
   377     boolean removeEq(Object o) {
   378         for (int i = 0; i < size; i++) {
   379             if (o == queue[i]) {
   380                 removeAt(i);
   381                 return true;
   382             }
   383         }
   384         return false;
   385     }
   386 
   387     /**
   388      * Returns {@code true} if this queue contains the specified element.
   389      * More formally, returns {@code true} if and only if this queue contains
   390      * at least one element {@code e} such that {@code o.equals(e)}.
   391      *
   392      * @param o object to be checked for containment in this queue
   393      * @return {@code true} if this queue contains the specified element
   394      */
   395     public boolean contains(Object o) {
   396         return indexOf(o) != -1;
   397     }
   398 
   399     /**
   400      * Returns an array containing all of the elements in this queue.
   401      * The elements are in no particular order.
   402      *
   403      * <p>The returned array will be "safe" in that no references to it are
   404      * maintained by this queue.  (In other words, this method must allocate
   405      * a new array).  The caller is thus free to modify the returned array.
   406      *
   407      * <p>This method acts as bridge between array-based and collection-based
   408      * APIs.
   409      *
   410      * @return an array containing all of the elements in this queue
   411      */
   412     public Object[] toArray() {
   413         return Arrays.copyOf(queue, size);
   414     }
   415 
   416     /**
   417      * Returns an array containing all of the elements in this queue; the
   418      * runtime type of the returned array is that of the specified array.
   419      * The returned array elements are in no particular order.
   420      * If the queue fits in the specified array, it is returned therein.
   421      * Otherwise, a new array is allocated with the runtime type of the
   422      * specified array and the size of this queue.
   423      *
   424      * <p>If the queue fits in the specified array with room to spare
   425      * (i.e., the array has more elements than the queue), the element in
   426      * the array immediately following the end of the collection is set to
   427      * {@code null}.
   428      *
   429      * <p>Like the {@link #toArray()} method, this method acts as bridge between
   430      * array-based and collection-based APIs.  Further, this method allows
   431      * precise control over the runtime type of the output array, and may,
   432      * under certain circumstances, be used to save allocation costs.
   433      *
   434      * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
   435      * The following code can be used to dump the queue into a newly
   436      * allocated array of <tt>String</tt>:
   437      *
   438      * <pre>
   439      *     String[] y = x.toArray(new String[0]);</pre>
   440      *
   441      * Note that <tt>toArray(new Object[0])</tt> is identical in function to
   442      * <tt>toArray()</tt>.
   443      *
   444      * @param a the array into which the elements of the queue are to
   445      *          be stored, if it is big enough; otherwise, a new array of the
   446      *          same runtime type is allocated for this purpose.
   447      * @return an array containing all of the elements in this queue
   448      * @throws ArrayStoreException if the runtime type of the specified array
   449      *         is not a supertype of the runtime type of every element in
   450      *         this queue
   451      * @throws NullPointerException if the specified array is null
   452      */
   453     public <T> T[] toArray(T[] a) {
   454         if (a.length < size)
   455             // Make a new array of a's runtime type, but my contents:
   456             return (T[]) Arrays.copyOf(queue, size, a.getClass());
   457         System.arraycopy(queue, 0, a, 0, size);
   458         if (a.length > size)
   459             a[size] = null;
   460         return a;
   461     }
   462 
   463     /**
   464      * Returns an iterator over the elements in this queue. The iterator
   465      * does not return the elements in any particular order.
   466      *
   467      * @return an iterator over the elements in this queue
   468      */
   469     public Iterator<E> iterator() {
   470         return new Itr();
   471     }
   472 
   473     private final class Itr implements Iterator<E> {
   474         /**
   475          * Index (into queue array) of element to be returned by
   476          * subsequent call to next.
   477          */
   478         private int cursor = 0;
   479 
   480         /**
   481          * Index of element returned by most recent call to next,
   482          * unless that element came from the forgetMeNot list.
   483          * Set to -1 if element is deleted by a call to remove.
   484          */
   485         private int lastRet = -1;
   486 
   487         /**
   488          * A queue of elements that were moved from the unvisited portion of
   489          * the heap into the visited portion as a result of "unlucky" element
   490          * removals during the iteration.  (Unlucky element removals are those
   491          * that require a siftup instead of a siftdown.)  We must visit all of
   492          * the elements in this list to complete the iteration.  We do this
   493          * after we've completed the "normal" iteration.
   494          *
   495          * We expect that most iterations, even those involving removals,
   496          * will not need to store elements in this field.
   497          */
   498         private ArrayDeque<E> forgetMeNot = null;
   499 
   500         /**
   501          * Element returned by the most recent call to next iff that
   502          * element was drawn from the forgetMeNot list.
   503          */
   504         private E lastRetElt = null;
   505 
   506         /**
   507          * The modCount value that the iterator believes that the backing
   508          * Queue should have.  If this expectation is violated, the iterator
   509          * has detected concurrent modification.
   510          */
   511         private int expectedModCount = modCount;
   512 
   513         public boolean hasNext() {
   514             return cursor < size ||
   515                 (forgetMeNot != null && !forgetMeNot.isEmpty());
   516         }
   517 
   518         public E next() {
   519             if (expectedModCount != modCount)
   520                 throw new ConcurrentModificationException();
   521             if (cursor < size)
   522                 return (E) queue[lastRet = cursor++];
   523             if (forgetMeNot != null) {
   524                 lastRet = -1;
   525                 lastRetElt = forgetMeNot.poll();
   526                 if (lastRetElt != null)
   527                     return lastRetElt;
   528             }
   529             throw new NoSuchElementException();
   530         }
   531 
   532         public void remove() {
   533             if (expectedModCount != modCount)
   534                 throw new ConcurrentModificationException();
   535             if (lastRet != -1) {
   536                 E moved = PriorityQueue.this.removeAt(lastRet);
   537                 lastRet = -1;
   538                 if (moved == null)
   539                     cursor--;
   540                 else {
   541                     if (forgetMeNot == null)
   542                         forgetMeNot = new ArrayDeque<>();
   543                     forgetMeNot.add(moved);
   544                 }
   545             } else if (lastRetElt != null) {
   546                 PriorityQueue.this.removeEq(lastRetElt);
   547                 lastRetElt = null;
   548             } else {
   549                 throw new IllegalStateException();
   550             }
   551             expectedModCount = modCount;
   552         }
   553     }
   554 
   555     public int size() {
   556         return size;
   557     }
   558 
   559     /**
   560      * Removes all of the elements from this priority queue.
   561      * The queue will be empty after this call returns.
   562      */
   563     public void clear() {
   564         modCount++;
   565         for (int i = 0; i < size; i++)
   566             queue[i] = null;
   567         size = 0;
   568     }
   569 
   570     public E poll() {
   571         if (size == 0)
   572             return null;
   573         int s = --size;
   574         modCount++;
   575         E result = (E) queue[0];
   576         E x = (E) queue[s];
   577         queue[s] = null;
   578         if (s != 0)
   579             siftDown(0, x);
   580         return result;
   581     }
   582 
   583     /**
   584      * Removes the ith element from queue.
   585      *
   586      * Normally this method leaves the elements at up to i-1,
   587      * inclusive, untouched.  Under these circumstances, it returns
   588      * null.  Occasionally, in order to maintain the heap invariant,
   589      * it must swap a later element of the list with one earlier than
   590      * i.  Under these circumstances, this method returns the element
   591      * that was previously at the end of the list and is now at some
   592      * position before i. This fact is used by iterator.remove so as to
   593      * avoid missing traversing elements.
   594      */
   595     private E removeAt(int i) {
   596         assert i >= 0 && i < size;
   597         modCount++;
   598         int s = --size;
   599         if (s == i) // removed last element
   600             queue[i] = null;
   601         else {
   602             E moved = (E) queue[s];
   603             queue[s] = null;
   604             siftDown(i, moved);
   605             if (queue[i] == moved) {
   606                 siftUp(i, moved);
   607                 if (queue[i] != moved)
   608                     return moved;
   609             }
   610         }
   611         return null;
   612     }
   613 
   614     /**
   615      * Inserts item x at position k, maintaining heap invariant by
   616      * promoting x up the tree until it is greater than or equal to
   617      * its parent, or is the root.
   618      *
   619      * To simplify and speed up coercions and comparisons. the
   620      * Comparable and Comparator versions are separated into different
   621      * methods that are otherwise identical. (Similarly for siftDown.)
   622      *
   623      * @param k the position to fill
   624      * @param x the item to insert
   625      */
   626     private void siftUp(int k, E x) {
   627         if (comparator != null)
   628             siftUpUsingComparator(k, x);
   629         else
   630             siftUpComparable(k, x);
   631     }
   632 
   633     private void siftUpComparable(int k, E x) {
   634         Comparable<? super E> key = (Comparable<? super E>) x;
   635         while (k > 0) {
   636             int parent = (k - 1) >>> 1;
   637             Object e = queue[parent];
   638             if (key.compareTo((E) e) >= 0)
   639                 break;
   640             queue[k] = e;
   641             k = parent;
   642         }
   643         queue[k] = key;
   644     }
   645 
   646     private void siftUpUsingComparator(int k, E x) {
   647         while (k > 0) {
   648             int parent = (k - 1) >>> 1;
   649             Object e = queue[parent];
   650             if (comparator.compare(x, (E) e) >= 0)
   651                 break;
   652             queue[k] = e;
   653             k = parent;
   654         }
   655         queue[k] = x;
   656     }
   657 
   658     /**
   659      * Inserts item x at position k, maintaining heap invariant by
   660      * demoting x down the tree repeatedly until it is less than or
   661      * equal to its children or is a leaf.
   662      *
   663      * @param k the position to fill
   664      * @param x the item to insert
   665      */
   666     private void siftDown(int k, E x) {
   667         if (comparator != null)
   668             siftDownUsingComparator(k, x);
   669         else
   670             siftDownComparable(k, x);
   671     }
   672 
   673     private void siftDownComparable(int k, E x) {
   674         Comparable<? super E> key = (Comparable<? super E>)x;
   675         int half = size >>> 1;        // loop while a non-leaf
   676         while (k < half) {
   677             int child = (k << 1) + 1; // assume left child is least
   678             Object c = queue[child];
   679             int right = child + 1;
   680             if (right < size &&
   681                 ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
   682                 c = queue[child = right];
   683             if (key.compareTo((E) c) <= 0)
   684                 break;
   685             queue[k] = c;
   686             k = child;
   687         }
   688         queue[k] = key;
   689     }
   690 
   691     private void siftDownUsingComparator(int k, E x) {
   692         int half = size >>> 1;
   693         while (k < half) {
   694             int child = (k << 1) + 1;
   695             Object c = queue[child];
   696             int right = child + 1;
   697             if (right < size &&
   698                 comparator.compare((E) c, (E) queue[right]) > 0)
   699                 c = queue[child = right];
   700             if (comparator.compare(x, (E) c) <= 0)
   701                 break;
   702             queue[k] = c;
   703             k = child;
   704         }
   705         queue[k] = x;
   706     }
   707 
   708     /**
   709      * Establishes the heap invariant (described above) in the entire tree,
   710      * assuming nothing about the order of the elements prior to the call.
   711      */
   712     private void heapify() {
   713         for (int i = (size >>> 1) - 1; i >= 0; i--)
   714             siftDown(i, (E) queue[i]);
   715     }
   716 
   717     /**
   718      * Returns the comparator used to order the elements in this
   719      * queue, or {@code null} if this queue is sorted according to
   720      * the {@linkplain Comparable natural ordering} of its elements.
   721      *
   722      * @return the comparator used to order this queue, or
   723      *         {@code null} if this queue is sorted according to the
   724      *         natural ordering of its elements
   725      */
   726     public Comparator<? super E> comparator() {
   727         return comparator;
   728     }
   729 
   730 
   731 }