以下代码对于传递编译是合法的。为什么可以将PriorityQueue定义为仅采用可比较的实例?
...
PriorityQueue<Object> q = new PriorityQueue<Object>();
q.add(new Object());
...
但它抛出了预期的例外:
Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.Comparable
at java.util.PriorityQueue.siftUpComparable(PriorityQueue.java:595)
at java.util.PriorityQueue.siftUp(PriorityQueue.java:591)
at java.util.PriorityQueue.offer(PriorityQueue.java:291)
at java.util.PriorityQueue.add(PriorityQueue.java:268)
at ReentrantLockExample.main(ReentrantLockExample.java:12)
答案 0 :(得分:5)
因为 允许您为不是Comparator
的元素类型指定自己的Comparable
。这也会影响TreeSet
,TreeMap
以及基本上所有其他已排序的集合。
如果您在自己的代码中尝试避免使用它,请选择工厂方法来构造,因为您可以在不同的工厂方法上指定不同的类型约束。例如,Guava provides
<E extends Comparable> TreeSet<E> Sets.newTreeSet();
<E> TreeSet<E> Sets.newTreeSet(Comparator<? super E> comparator);
答案 1 :(得分:1)
只要您提供Comparable
,就可以存储未实现Comparator
,的对象。
优先级队列的元素按照其自然顺序排序,或者在队列构造时提供
Comparator
,具体取决于使用的构造函数。优先级队列不允许null
个元素。依赖于自然排序的优先级队列也不允许插入不可比较的对象(这样做可能会导致ClassCastException
)。