views:

207

answers:

2

I'm trying to use a PriorityQueue to order objects using a Comparator.

This can be achieved easily, but the objects class variables (with which the comparator calculates priority) may change after the initial insertion. Most people have suggested the simple solution of removing the object, updating the values and reinserting it again, as this is when the priority queue's comparator is put into action.

Is there a better way other than just creating a wrapper class around the PriorityQueue to do this?

+2  A: 

You have to remove and re-insert, as the queue works by putting new elements in the appropriate position when they are inserted. This is much faster than the alternative of finding the highest-priority element every time you pull out of the queue. The drawback is that you cannot change the priority after the element has been inserted. A TreeMap has the same limitation (as does a HashMap, which also breaks when the hashcode of its elements changes after insertion).

If you want to write a wrapper, you can move the comparison code from enqueue to dequeue. You would not need to sort at enqueue time anymore (because the order it creates would not be reliable anyway if you allow changes).

But this will perform worse, and you want to synchronize on the queue if you change any of the priorities. Since you need to add synchronization code when updating priorities, you might as well just dequeue and enqueue (you need the reference to the queue in both cases).

Thilo
I see, so removing the object altering it and reinserting it IS the best option?
Marcus Whybrow
I believe so. Of course, this can only be done if the code doing the altering is aware of any queues the object is waiting in.
Thilo
Yes, this is the case in my case.
Marcus Whybrow
A: 

I don't know if there is a Java implementation, but if you're changing key values alot, you can use a Fibonnaci heap, which has O(1) amortized cost to decrease a key value of an entry in the heap, rather than O(log(n)) as in an ordinary heap.

Jon McCaffrey
The JDK does not have a FibonacciHeap although it does exist from a third party. I know that once an object is added to my queue, it can only increase in priority, so does anyone know of an implementation with O(1) to swap two elements? such as the decrease functionality. Or can this be achieved easily with any implementation by swapping elements instead of with the PriorityQueue deleting and reinserting which would take O(1) and O(log(n)) respectively?
Marcus Whybrow