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