Andrew Wyld
Andrew Wyld

Reputation: 7258

Does a PriorityQueue allow elements already within the queue to be reordered?

I want to augment or lower the priority of items in a PriorityQueue: for example, I might be downloading a long list of images and suddenly want the thirtieth one to have highest priority.

As I understand it, poll() always returns the queue object with the lowest value (as determined by a comparator). If I can lower the value of an item already in a queue (e.g. if this value is determined by an int in the object and I reduce the int value in some other function), will it be returned first by poll(), or is the sorting that allows poll() to do this done at insert time (e.g. by bubbling new queue elements down a list till they reach their "natural" depth)?

If this is done on a PriorityBlockingQueue, could it cause concurrency issues?

Upvotes: 1

Views: 3312

Answers (3)

Peter Lawrey
Peter Lawrey

Reputation: 533930

If you iterate over a priority queue, you will find it is in no particular order (except the first element) If you want to change the order, I suggest you create another priority queue.

If you wan to change the position of one entry, I suggest you remove it, change its fields as required and add it again.

Upvotes: 0

Qwerky
Qwerky

Reputation: 18455

If you look at the source code, every time you poll() on a PriorityQueue it resifts, but it always returns the item that was at the top before the sift.

public class PQ {

  int priority;

  public PQ(int priority) {
    this.priority = priority;
  }

  public static void main(String[] args) {

    PQ one = new PQ(1);
    PQ two = new PQ(2);
    PQ three = new PQ(3);
    PQ four = new PQ(4);
    PQ five = new PQ(5);

    PriorityQueue<PQ> q = new PriorityQueue<PQ>(3, new Comparator<PQ>() {
      @Override
      public int compare(PQ o1, PQ o2) {
        return o1.priority-o2.priority;
      }
    });

    q.add(three);
    q.add(one);
    q.add(four);
    q.add(two);
    q.add(five);

    //Prints;
    //PQ-1
    //PQ-2
    //PQ-3
    //PQ-4
    //PQ-5
    while (!q.isEmpty()) {
      System.out.println(q.poll());
    }

    q.add(three);
    q.add(one);
    q.add(four);
    q.add(two);
    q.add(five);

    //Change the priority after it has been queued
    four.priority = 10;

    //Prints;
    //PQ-1
    //PQ-2
    //PQ-3
    //PQ-5
    //PQ-10
    while (!q.isEmpty()) {
      System.out.println(q.poll());
    }

    //Reset the priority
    four.priority = 4;

    q.add(three);
    q.add(one);
    q.add(four);
    q.add(two);
    q.add(five);

    //Change the priority after it has been queued
    four.priority = 0;

    //Prints;
    //PQ-1
    //PQ-0
    //PQ-2
    //PQ-3
    //PQ-5
    while (!q.isEmpty()) {
      System.out.println(q.poll());
    }
  }

  public String toString() {
    return "PQ-" + priority;
  }

}

Upvotes: 2

nos
nos

Reputation: 229342

None of the collections in Java automatically reorders elements if you change the property that determine their order. For collections that depend on the .hashCode() , .equals() or some comparator, you are not allowed to change the object while it resides in the collection so that the hashcode/equals or comparator would yield different values.

You have to remove, change, re-insert the object if you want to change its priority within a PriorityQueue.

Upvotes: 6

Related Questions