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

久未见 提交于 2019-12-02 11:03:04

问题


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?


回答1:


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.




回答2:


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;
  }

}



回答3:


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.



来源:https://stackoverflow.com/questions/8067924/does-a-priorityqueue-allow-elements-already-within-the-queue-to-be-reordered

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!