I expect the two code snippets to produce the same result, yet they don't. Why? The only difference is the Comparator passed to the PriorityQueue constructor.
import java.util.Collections;
import java.util.PriorityQueue;
public class PriorityQueueTest {
public static void main(String[] args) {
PriorityQueue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());
int[] arr = {2,3,9,8,4};
for (int i=0; i<arr.length; i ) {
pq.add(arr[i]);
}
while(pq.size()>0) {
System.out.println(pq.poll());
}
}
}
Output (correct / expected):
9
8
4
3
2
import java.util.Collections;
import java.util.PriorityQueue;
public class PriorityQueueTest {
public static void main(String[] args) {
PriorityQueue<Integer> pq = new PriorityQueue<>((a,b) -> a>b ? 0 : 1);
int[] arr = {2,3,9,8,4};
for (int i=0; i<arr.length; i ) {
pq.add(arr[i]);
}
while(pq.size()>0) {
System.out.println(pq.poll());
}
}
}
Output (wrong / unexpected):
2
9
8
4
3
CodePudding user response:
Comparators must return 3 states: negative, 0 or positive, and must be self consistent such that compare(a,b) has same sign as -compare(b,a) when a!=b, and zero if a.equals(b).
Your comparator does not satisfy these conditions. You are fortunate your answer works, but if you omit the 0 case in other comparators you may have issues in future.
Instead use:
PriorityQueue<Integer> pq = new PriorityQueue<>((a,b) -> a==b ? 0 : a>b ? -1 : 1);
The above returns the order of elements you expect as for Collections.reverseOrder().
CodePudding user response:
What I was missing is that returning a 0 in the comparator indicates that the values are equal.
Changing comparator to the following orders things correctly
(a,b) -> a>=b ? -1 : 1
